mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-05-06 11:29:55 -05:00
Changed content in the module to content from the gaiamodule
This commit is contained in:
@@ -25,38 +25,47 @@
|
||||
include(${OPENSPACE_CMAKE_EXT_DIR}/module_definition.cmake)
|
||||
|
||||
set(HEADER_FILES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/galaxymodule.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rendering/galaxyraycaster.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablegalaxy.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tasks/milkywayconversiontask.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tasks/milkywaypointsconversiontask.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/gaiamodule.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablegaiastars.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rendering/octreemanager.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rendering/octreeculler.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tasks/readfilejob.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tasks/readfitstask.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tasks/readspecktask.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tasks/constructoctreetask.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rendering/gaiaoptions.h
|
||||
)
|
||||
source_group("Header Files" FILES ${HEADER_FILES})
|
||||
|
||||
set(SOURCE_FILES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/galaxymodule.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rendering/galaxyraycaster.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablegalaxy.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tasks/milkywayconversiontask.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tasks/milkywaypointsconversiontask.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/gaiamodule.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablegaiastars.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rendering/octreemanager.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rendering/octreeculler.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tasks/readfilejob.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tasks/readfitstask.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tasks/readspecktask.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tasks/constructoctreetask.cpp
|
||||
)
|
||||
source_group("Source Files" FILES ${SOURCE_FILES})
|
||||
|
||||
set(SHADER_FILES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/shaders/galaxyraycast.glsl
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/shaders/billboard_vs.glsl
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/shaders/billboard_fs.glsl
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/shaders/billboard_ge.glsl
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/shaders/points_fs.glsl
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/shaders/points_vs.glsl
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/shaders/raycasterbounds_fs.glsl
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/shaders/raycasterbounds_vs.glsl
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/shaders/gaia_vbo_vs.glsl
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/shaders/gaia_ssbo_vs.glsl
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/shaders/gaia_billboard_nofbo_fs.glsl
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/shaders/gaia_billboard_fs.glsl
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/shaders/gaia_billboard_ge.glsl
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/shaders/gaia_point_fs.glsl
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/shaders/gaia_point_ge.glsl
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/shaders/gaia_tonemapping_vs.glsl
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/shaders/gaia_tonemapping_point_fs.glsl
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/shaders/gaia_tonemapping_billboard_fs.glsl
|
||||
)
|
||||
source_group("Shader Files" FILES ${SHADER_FILES})
|
||||
|
||||
create_new_module(
|
||||
"Galaxy"
|
||||
galaxy
|
||||
"Gaia"
|
||||
gaia
|
||||
STATIC
|
||||
${HEADER_FILES} ${SOURCE_FILES} ${SHADER_FILES}
|
||||
)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
set(DEFAULT_MODULE ON)
|
||||
|
||||
set (OPENSPACE_DEPENDENCIES
|
||||
volume
|
||||
space
|
||||
)
|
||||
set(OPENSPACE_DEPENDENCIES
|
||||
fitsfilereader
|
||||
globebrowsing
|
||||
)
|
||||
|
||||
+24
-13
@@ -22,22 +22,33 @@
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#version __CONTEXT__
|
||||
#ifndef __OPENSPACE_MODULE_GAIA___GAIAOPTIONS___H__
|
||||
#define __OPENSPACE_MODULE_GAIA___GAIAOPTIONS___H__
|
||||
|
||||
layout(location = 0) in vec4 vertPosition;
|
||||
namespace openspace::gaia {
|
||||
|
||||
out vec3 modelPosition;
|
||||
out vec4 viewPosition;
|
||||
enum RenderOption {
|
||||
Static = 0,
|
||||
Color = 1,
|
||||
Motion = 2
|
||||
};
|
||||
|
||||
uniform mat4 projectionTransform;
|
||||
uniform mat4 modelViewTransform;
|
||||
enum FileReaderOption {
|
||||
Fits = 0,
|
||||
Speck = 1,
|
||||
BinaryRaw = 2,
|
||||
BinaryOctree = 3,
|
||||
StreamOctree = 4
|
||||
};
|
||||
|
||||
enum ShaderOption {
|
||||
Point_SSBO = 0,
|
||||
Point_VBO = 1,
|
||||
Billboard_SSBO = 2,
|
||||
Billboard_VBO = 3,
|
||||
Billboard_SSBO_noFBO = 4
|
||||
};
|
||||
|
||||
void main() {
|
||||
modelPosition = vertPosition.xyz;
|
||||
viewPosition = modelViewTransform*vertPosition;
|
||||
} // namespace openspace::gaiamission
|
||||
|
||||
// project the position to view space
|
||||
gl_Position = projectionTransform * viewPosition;
|
||||
gl_Position.z = 0.0;
|
||||
}
|
||||
#endif // __OPENSPACE_MODULE_GAIA___GAIAOPTIONS___H__
|
||||
@@ -1,185 +0,0 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2020 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
|
||||
* software and associated documentation files (the "Software"), to deal in the Software *
|
||||
* without restriction, including without limitation the rights to use, copy, modify, *
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
|
||||
* permit persons to whom the Software is furnished to do so, subject to the following *
|
||||
* conditions: *
|
||||
* *
|
||||
* The above copyright notice and this permission notice shall be included in all copies *
|
||||
* or substantial portions of the Software. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#include <modules/galaxy/rendering/galaxyraycaster.h>
|
||||
|
||||
#include <openspace/rendering/renderable.h>
|
||||
#include <openspace/util/updatestructures.h>
|
||||
#include <ghoul/opengl/ghoul_gl.h>
|
||||
#include <ghoul/opengl/programobject.h>
|
||||
#include <ghoul/opengl/textureunit.h>
|
||||
#include <ghoul/opengl/texture.h>
|
||||
|
||||
namespace {
|
||||
constexpr const char* GlslRaycastPath =
|
||||
"${MODULES}/galaxy/shaders/galaxyraycast.glsl";
|
||||
constexpr const char* GlslBoundsVsPath =
|
||||
"${MODULES}/galaxy/shaders/raycasterbounds_vs.glsl";
|
||||
constexpr const char* GlslBoundsFsPath =
|
||||
"${MODULES}/galaxy/shaders/raycasterbounds_fs.glsl";
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
GalaxyRaycaster::GalaxyRaycaster(ghoul::opengl::Texture& texture)
|
||||
: _boundingBox(glm::vec3(1.0))
|
||||
, _texture(texture)
|
||||
, _textureUnit(nullptr)
|
||||
{}
|
||||
|
||||
void GalaxyRaycaster::initialize() {
|
||||
_boundingBox.initialize();
|
||||
}
|
||||
|
||||
void GalaxyRaycaster::renderEntryPoints(const RenderData& data,
|
||||
ghoul::opengl::ProgramObject& program)
|
||||
{
|
||||
program.setUniform("modelViewTransform", glm::mat4(modelViewTransform(data)));
|
||||
program.setUniform("projectionTransform", data.camera.projectionMatrix());
|
||||
|
||||
// Cull back face
|
||||
glEnable(GL_CULL_FACE);
|
||||
glCullFace(GL_BACK);
|
||||
|
||||
// Render bounding geometry
|
||||
_boundingBox.render();
|
||||
}
|
||||
|
||||
void GalaxyRaycaster::renderExitPoints(const RenderData& data,
|
||||
ghoul::opengl::ProgramObject& program)
|
||||
{
|
||||
// Uniforms
|
||||
program.setUniform("modelViewTransform", glm::mat4(modelViewTransform(data)));
|
||||
program.setUniform("projectionTransform", data.camera.projectionMatrix());
|
||||
|
||||
// Cull front face
|
||||
glEnable(GL_CULL_FACE);
|
||||
glCullFace(GL_FRONT);
|
||||
|
||||
// Render bounding geometry
|
||||
_boundingBox.render();
|
||||
|
||||
// Restore defaults
|
||||
glCullFace(GL_BACK);
|
||||
}
|
||||
|
||||
glm::dmat4 GalaxyRaycaster::modelViewTransform(const RenderData& data) {
|
||||
glm::dmat4 modelTransform =
|
||||
glm::translate(glm::dmat4(1.0), data.modelTransform.translation) *
|
||||
glm::dmat4(data.modelTransform.rotation) *
|
||||
glm::scale(glm::dmat4(1.0), glm::dvec3(data.modelTransform.scale)) *
|
||||
glm::dmat4(_modelTransform);
|
||||
|
||||
return data.camera.combinedViewMatrix() * modelTransform;
|
||||
}
|
||||
|
||||
void GalaxyRaycaster::preRaycast(const RaycastData& data,
|
||||
ghoul::opengl::ProgramObject& program)
|
||||
{
|
||||
const std::string colorUniformName = "color" + std::to_string(data.id);
|
||||
const std::string stepSizeUniformName = "maxStepSize" + std::to_string(data.id);
|
||||
const std::string galaxyTextureUniformName = "galaxyTexture" +
|
||||
std::to_string(data.id);
|
||||
const std::string volumeAspectUniformName = "aspect" + std::to_string(data.id);
|
||||
const std::string opacityCoefficientUniformName = "opacityCoefficient" +
|
||||
std::to_string(data.id);
|
||||
|
||||
const std::string absorptionMultiplyUniformName = "absorptionMultiply" +
|
||||
std::to_string(data.id);
|
||||
|
||||
const std::string emissionMultiplyUniformName = "emissionMultiply" +
|
||||
std::to_string(data.id);
|
||||
|
||||
program.setUniform(volumeAspectUniformName, _aspect);
|
||||
program.setUniform(stepSizeUniformName, _stepSize);
|
||||
program.setUniform(opacityCoefficientUniformName, _opacityCoefficient);
|
||||
program.setUniform(absorptionMultiplyUniformName, _absorptionMultiply);
|
||||
program.setUniform(emissionMultiplyUniformName, _emissionMultiply);
|
||||
|
||||
_textureUnit = std::make_unique<ghoul::opengl::TextureUnit>();
|
||||
_textureUnit->activate();
|
||||
_texture.bind();
|
||||
program.setUniform(galaxyTextureUniformName, *_textureUnit);
|
||||
}
|
||||
|
||||
void GalaxyRaycaster::postRaycast(const RaycastData&, ghoul::opengl::ProgramObject&) {
|
||||
_textureUnit = nullptr; // release texture unit.
|
||||
}
|
||||
|
||||
bool GalaxyRaycaster::isCameraInside(const RenderData& data, glm::vec3& localPosition) {
|
||||
glm::vec4 modelPos = glm::inverse(modelViewTransform(data)) *
|
||||
glm::vec4(0.f, 0.f, 0.f, 1.f);
|
||||
|
||||
localPosition = (glm::vec3(modelPos) + glm::vec3(0.5));
|
||||
|
||||
return (localPosition.x > 0 && localPosition.x < 1 &&
|
||||
localPosition.y > 0 && localPosition.y < 1 &&
|
||||
localPosition.z > 0 && localPosition.z < 1);
|
||||
}
|
||||
|
||||
std::string GalaxyRaycaster::boundsVertexShaderPath() const {
|
||||
return GlslBoundsVsPath;
|
||||
}
|
||||
|
||||
std::string GalaxyRaycaster::boundsFragmentShaderPath() const {
|
||||
return GlslBoundsFsPath;
|
||||
}
|
||||
|
||||
std::string GalaxyRaycaster::raycasterPath() const {
|
||||
return GlslRaycastPath;
|
||||
}
|
||||
|
||||
std::string GalaxyRaycaster::helperPath() const {
|
||||
return ""; // no helper file
|
||||
}
|
||||
|
||||
void GalaxyRaycaster::setAspect(const glm::vec3& aspect) {
|
||||
_aspect = aspect / std::max(std::max(aspect.x, aspect.y), aspect.z);
|
||||
}
|
||||
|
||||
void GalaxyRaycaster::setModelTransform(glm::mat4 transform) {
|
||||
_modelTransform = transform;
|
||||
}
|
||||
|
||||
void GalaxyRaycaster::setOpacityCoefficient(float opacityCoefficient) {
|
||||
_opacityCoefficient = opacityCoefficient;
|
||||
}
|
||||
|
||||
void GalaxyRaycaster::setAbsorptionMultiplier(float absorptionMultiply) {
|
||||
_absorptionMultiply = absorptionMultiply;
|
||||
}
|
||||
|
||||
void GalaxyRaycaster::setEmissionMultiplier(float emissionMultiply) {
|
||||
_emissionMultiply = emissionMultiply;
|
||||
}
|
||||
|
||||
void GalaxyRaycaster::setTime(double time) {
|
||||
_time = time;
|
||||
}
|
||||
|
||||
void GalaxyRaycaster::setStepSize(float stepSize) {
|
||||
_stepSize = stepSize;
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
@@ -1,95 +0,0 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2020 *
|
||||
* *
|
||||
* 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_MODULE_GALAXY___GALAXYRAYCASTER___H__
|
||||
#define __OPENSPACE_MODULE_GALAXY___GALAXYRAYCASTER___H__
|
||||
|
||||
#include <openspace/rendering/volumeraycaster.h>
|
||||
|
||||
#include <openspace/util/boxgeometry.h>
|
||||
#include <ghoul/glm.h>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
namespace ghoul::opengl {
|
||||
class Texture;
|
||||
class TextureUnit;
|
||||
class ProgramObject;
|
||||
} // namespace ghoul::opengl
|
||||
|
||||
namespace openspace {
|
||||
|
||||
struct RenderData;
|
||||
struct RaycastData;
|
||||
|
||||
class GalaxyRaycaster : public VolumeRaycaster {
|
||||
public:
|
||||
GalaxyRaycaster(ghoul::opengl::Texture& texture);
|
||||
|
||||
virtual ~GalaxyRaycaster() = default;
|
||||
void initialize();
|
||||
|
||||
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;
|
||||
bool isCameraInside(const RenderData& data,
|
||||
glm::vec3& localPosition) override;
|
||||
|
||||
std::string boundsVertexShaderPath() const override;
|
||||
std::string boundsFragmentShaderPath() const override;
|
||||
std::string raycasterPath() const override;
|
||||
std::string helperPath() const override;
|
||||
|
||||
void setAspect(const glm::vec3& aspect);
|
||||
void setModelTransform(glm::mat4 transform);
|
||||
void setTime(double time);
|
||||
void setStepSize(float stepSize);
|
||||
void setOpacityCoefficient(float opacityCoefficient);
|
||||
void setAbsorptionMultiplier(float absorptionMultiply);
|
||||
void setEmissionMultiplier(float emissionMultiply);
|
||||
|
||||
private:
|
||||
glm::dmat4 modelViewTransform(const RenderData& data);
|
||||
|
||||
BoxGeometry _boundingBox;
|
||||
float _stepSize = 0.f;
|
||||
glm::mat4 _modelTransform = glm::mat4(1.f);
|
||||
glm::vec3 _aspect = glm::vec3(0.f);
|
||||
double _time = 0.0;
|
||||
float _opacityCoefficient = 0.f;
|
||||
float _absorptionMultiply = 0.f;
|
||||
float _emissionMultiply = 0.f;
|
||||
ghoul::opengl::Texture& _texture;
|
||||
std::unique_ptr<ghoul::opengl::TextureUnit> _textureUnit;
|
||||
|
||||
}; // GalaxyRaycaster
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
#endif // __OPENSPACE_MODULE_GALAXY___GALAXYRAYCASTER___H__
|
||||
+46
-61
@@ -22,76 +22,61 @@
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#include <modules/galaxy/tasks/milkywaypointsconversiontask.h>
|
||||
#include <modules/gaia/rendering/octreeculler.h>
|
||||
|
||||
#include <openspace/documentation/documentation.h>
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <ghoul/glm.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
|
||||
namespace openspace {
|
||||
|
||||
/*MilkywayPointsConversionTask::MilkywayPointsConversionTask(
|
||||
const std::string& inFilename,
|
||||
const std::string& outFilename)
|
||||
: _inFilename(inFilename)
|
||||
, _outFilename(outFilename) {}*/
|
||||
|
||||
MilkywayPointsConversionTask::MilkywayPointsConversionTask(const ghoul::Dictionary&) {}
|
||||
|
||||
std::string MilkywayPointsConversionTask::description() {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
void MilkywayPointsConversionTask::perform(const Task::ProgressCallback& progressCallback)
|
||||
{
|
||||
std::ifstream in(_inFilename, std::ios::in);
|
||||
std::ofstream out(_outFilename, std::ios::out | std::ios::binary);
|
||||
|
||||
std::string format;
|
||||
int64_t nPoints;
|
||||
in >> format >> nPoints;
|
||||
|
||||
size_t nFloats = nPoints * 7;
|
||||
|
||||
std::vector<float> pointData(nFloats);
|
||||
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
float r;
|
||||
float g;
|
||||
float b;
|
||||
float a;
|
||||
|
||||
for (int64_t i = 0; i < nPoints; ++i) {
|
||||
in >> x >> y >> z >> r >> g >> b >> a;
|
||||
if (in.good()) {
|
||||
pointData[i * 7 + 0] = x;
|
||||
pointData[i * 7 + 1] = y;
|
||||
pointData[i * 7 + 2] = z;
|
||||
pointData[i * 7 + 3] = r;
|
||||
pointData[i * 7 + 4] = g;
|
||||
pointData[i * 7 + 5] = b;
|
||||
pointData[i * 7 + 6] = a;
|
||||
progressCallback(static_cast<float>(i + 1) / nPoints);
|
||||
}
|
||||
else {
|
||||
std::cout << "Failed to convert point data.";
|
||||
return;
|
||||
}
|
||||
namespace {
|
||||
bool intersects(const globebrowsing::AABB3& bb, const globebrowsing::AABB3& o) {
|
||||
return (bb.min.x <= o.max.x) && (o.min.x <= bb.max.x)
|
||||
&& (bb.min.y <= o.max.y) && (o.min.y <= bb.max.y)
|
||||
&& (bb.min.z <= o.max.z) && (o.min.z <= bb.max.z);
|
||||
}
|
||||
|
||||
out.write(reinterpret_cast<char*>(&nPoints), sizeof(int64_t));
|
||||
out.write(reinterpret_cast<char*>(pointData.data()), nFloats * sizeof(float));
|
||||
void expand(globebrowsing::AABB3& bb, const glm::vec3& p) {
|
||||
bb.min = glm::min(bb.min, p);
|
||||
bb.max = glm::max(bb.max, p);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
in.close();
|
||||
out.close();
|
||||
OctreeCuller::OctreeCuller(globebrowsing::AABB3 viewFrustum)
|
||||
: _viewFrustum(std::move(viewFrustum))
|
||||
{}
|
||||
|
||||
bool OctreeCuller::isVisible(const std::vector<glm::dvec4>& corners,
|
||||
const glm::dmat4& mvp)
|
||||
{
|
||||
createNodeBounds(corners, mvp);
|
||||
return intersects(_viewFrustum, _nodeBounds);
|
||||
}
|
||||
|
||||
documentation::Documentation MilkywayPointsConversionTask::documentation() {
|
||||
return documentation::Documentation();
|
||||
glm::vec2 OctreeCuller::getNodeSizeInPixels(const std::vector<glm::dvec4>& corners,
|
||||
const glm::dmat4& mvp,
|
||||
const glm::vec2& screenSize)
|
||||
{
|
||||
|
||||
createNodeBounds(corners, mvp);
|
||||
|
||||
// Screen space is mapped to [-1, 1] so divide by 2 and multiply with screen size.
|
||||
glm::vec3 size = (_nodeBounds.max - _nodeBounds.min) / 2.f;
|
||||
size = glm::abs(size);
|
||||
return glm::vec2(size.x * screenSize.x, size.y * screenSize.y);
|
||||
}
|
||||
|
||||
void OctreeCuller::createNodeBounds(const std::vector<glm::dvec4>& corners,
|
||||
const glm::dmat4& mvp)
|
||||
{
|
||||
// Create a bounding box in clipping space from node boundaries.
|
||||
_nodeBounds = globebrowsing::AABB3();
|
||||
|
||||
for (size_t i = 0; i < 8; ++i) {
|
||||
glm::dvec4 cornerClippingSpace = mvp * corners[i];
|
||||
glm::dvec4 ndc = (1.f / glm::abs(cornerClippingSpace.w)) * cornerClippingSpace;
|
||||
expand(_nodeBounds, glm::dvec3(ndc));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
+36
-19
@@ -22,38 +22,55 @@
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#ifndef __OPENSPACE_MODULE_GALAXY___MILKYWAYPOINTSCONVERSIONTASK_H__
|
||||
#define __OPENSPACE_MODULE_GALAXY___MILKYWAYPOINTSCONVERSIONTASK_H__
|
||||
#ifndef __OPENSPACE_MODULE_GAIA___OCTREECULLER___H__
|
||||
#define __OPENSPACE_MODULE_GAIA___OCTREECULLER___H__
|
||||
|
||||
#include <openspace/util/task.h>
|
||||
#include <modules/globebrowsing/src/basictypes.h>
|
||||
#include <vector>
|
||||
|
||||
#include <string>
|
||||
// TODO: Move /geometry/* to libOpenSpace so as not to depend on globebrowsing.
|
||||
|
||||
namespace openspace {
|
||||
|
||||
namespace documentation { struct Documentation; }
|
||||
|
||||
/**
|
||||
* Converts ascii based point data
|
||||
* int64_t n
|
||||
* (float x, float y, float z, float r, float g, float b) * n
|
||||
* to a binary (floating point) representation with the same layout.
|
||||
* Culls all octree nodes that are completely outside the view frustum.
|
||||
*
|
||||
* The frustum culling uses a 2D axis aligned bounding box for the OctreeNode in
|
||||
* screen space.
|
||||
*/
|
||||
class MilkywayPointsConversionTask : public Task {
|
||||
|
||||
class OctreeCuller {
|
||||
public:
|
||||
MilkywayPointsConversionTask(const ghoul::Dictionary& dictionary);
|
||||
virtual ~MilkywayPointsConversionTask() = default;
|
||||
|
||||
std::string description() override;
|
||||
void perform(const Task::ProgressCallback& progressCallback) override;
|
||||
/**
|
||||
* \param viewFrustum is the view space in normalized device coordinates space.
|
||||
* Hence it is an axis aligned bounding box and not a real frustum.
|
||||
*/
|
||||
OctreeCuller(globebrowsing::AABB3 viewFrustum);
|
||||
|
||||
static documentation::Documentation documentation();
|
||||
~OctreeCuller() = default;
|
||||
|
||||
/**
|
||||
* \return true if any part of the node is visible in the current view.
|
||||
*/
|
||||
bool isVisible(const std::vector<glm::dvec4>& corners, const glm::dmat4& mvp);
|
||||
|
||||
/**
|
||||
* \return the size [in pixels] of the node in clipping space.
|
||||
*/
|
||||
glm::vec2 getNodeSizeInPixels(const std::vector<glm::dvec4>& corners,
|
||||
const glm::dmat4& mvp, const glm::vec2& screenSize);
|
||||
|
||||
private:
|
||||
std::string _inFilename;
|
||||
std::string _outFilename;
|
||||
/**
|
||||
* Creates an axis-aligned bounding box containing all \p corners in clipping space.
|
||||
*/
|
||||
void createNodeBounds(const std::vector<glm::dvec4>& corners, const glm::dmat4& mvp);
|
||||
|
||||
const globebrowsing::AABB3 _viewFrustum;
|
||||
globebrowsing::AABB3 _nodeBounds;
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
#endif // __OPENSPACE_MODULE_GALAXY___MILKYWAYPOINTSCONVERSIONTASK_H__
|
||||
#endif // __OPENSPACE_MODULE_GAIA___OCTREECULLER___H__
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,387 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2020 *
|
||||
* *
|
||||
* 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_MODULE_GAIA___OCTREEMANAGER___H__
|
||||
#define __OPENSPACE_MODULE_GAIA___OCTREEMANAGER___H__
|
||||
|
||||
#include <modules/gaia/rendering/gaiaoptions.h>
|
||||
#include <ghoul/glm.h>
|
||||
#include <ghoul/opengl/ghoul_gl.h>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
#include <stack>
|
||||
#include <vector>
|
||||
|
||||
namespace openspace {
|
||||
|
||||
class OctreeCuller;
|
||||
|
||||
class OctreeManager {
|
||||
public:
|
||||
struct OctreeNode {
|
||||
std::shared_ptr<OctreeNode> Children[8];
|
||||
std::vector<float> posData;
|
||||
std::vector<float> colData;
|
||||
std::vector<float> velData;
|
||||
std::vector<std::pair<float, size_t>> magOrder;
|
||||
float originX;
|
||||
float originY;
|
||||
float originZ;
|
||||
float halfDimension;
|
||||
size_t numStars;
|
||||
bool isLeaf;
|
||||
bool isLoaded;
|
||||
bool hasLoadedDescendant;
|
||||
std::mutex loadingLock;
|
||||
int bufferIndex;
|
||||
unsigned long long octreePositionIndex;
|
||||
};
|
||||
|
||||
OctreeManager() = default;
|
||||
~OctreeManager() = default;
|
||||
|
||||
/**
|
||||
* Initializes a one layer Octree with root and 8 children that covers all stars.
|
||||
*
|
||||
* \param maxDist together with \param maxstarsPerNode (if defined) determines the
|
||||
* depth of the tree as well as how many nodes will be created.
|
||||
*/
|
||||
void initOctree(long long cpuRamBudget = 0, int maxDist = 0, int maxStarsPerNode = 0);
|
||||
|
||||
/**
|
||||
* Initializes a stack of size \param maxNodes that keeps track of all free spot in
|
||||
* buffer stream. Can be used to trigger a rebuild of buffer(s).
|
||||
*
|
||||
* \param useVBO defines if VBO or SSBO is used as buffer(s)
|
||||
* \param datasetFitInMemory defines if streaming of nodes during runtime is used
|
||||
*/
|
||||
void initBufferIndexStack(long long maxNodes, bool useVBO, bool datasetFitInMemory);
|
||||
|
||||
/**
|
||||
* Inserts star values in correct position in Octree. Makes use of a recursive
|
||||
* traversal strategy. Internally calls <code>insertInNode()</code>
|
||||
*/
|
||||
void insert(const std::vector<float>& starValues);
|
||||
|
||||
/**
|
||||
* Slices LOD data so only the MAX_STARS_PER_NODE brightest stars are stored in inner
|
||||
* nodes. If \p branchIndex is defined then only that branch will be sliced.
|
||||
* Calls <code>sliceNodeLodCache()</code> internally.
|
||||
*/
|
||||
void sliceLodData(size_t branchIndex = 8);
|
||||
|
||||
/**
|
||||
* Prints the whole tree structure, including number of stars per node, number of
|
||||
* nodes, tree depth and if node is a leaf.
|
||||
* Calls <code>printStarsPerNode(node, prefix)</code> internally.
|
||||
*/
|
||||
void printStarsPerNode() const;
|
||||
|
||||
/**
|
||||
* Used while streaming nodes from files. Checks if any nodes need to be loaded or
|
||||
* unloaded. If entire dataset fits in RAM then the whole dataset will be loaded
|
||||
* asynchronously. Otherwise only nodes close to the camera will be fetched.
|
||||
* When RAM stars to fill up least-recently used nodes will start to unload.
|
||||
* Calls <code>findAndFetchNeighborNode()</code> and
|
||||
* <code>removeNodesFromRam()</code> internally.
|
||||
*/
|
||||
void fetchSurroundingNodes(const glm::dvec3& cameraPos, size_t chunkSizeInBytes,
|
||||
const glm::ivec2& additionalNodes);
|
||||
|
||||
/**
|
||||
* Builds render data structure by traversing the Octree and checking for intersection
|
||||
* with view frustum. Every vector in map contains data for one node.
|
||||
* The corresponding integer key is the index where chunk should be inserted into
|
||||
* streaming buffer. Calls <code>checkNodeIntersection()</code> for every branch.
|
||||
* \pdeltaStars keeps track of how many stars that were added/removed this render
|
||||
* call.
|
||||
*/
|
||||
std::map<int, std::vector<float>> traverseData(const glm::dmat4& mvp,
|
||||
const glm::vec2& screenSize, int& deltaStars, gaia::RenderOption option,
|
||||
float lodPixelThreshold);
|
||||
|
||||
/**
|
||||
* Builds full render data structure by traversing all leaves in the Octree.
|
||||
*/
|
||||
std::vector<float> getAllData(gaia::RenderOption option);
|
||||
|
||||
/**
|
||||
* Removes all data from Octree, or only from a specific branch if specified.
|
||||
* \param branchIndex defined which branch to clear if defined.
|
||||
*/
|
||||
void clearAllData(int branchIndex = -1);
|
||||
|
||||
/**
|
||||
* Write entire Octree structure to a binary file. \param writeData defines if data
|
||||
* should be included or if only structure should be written to the file.
|
||||
* Calls <code>writeNodeToFile()</code> which recursively writes all nodes.
|
||||
*/
|
||||
void writeToFile(std::ofstream& outFileStream, bool writeData);
|
||||
|
||||
/**
|
||||
* Read a constructed Octree from a file. \returns the total number of (distinct)
|
||||
* stars read.
|
||||
*
|
||||
* \param readData defines if full data or only structure should be read.
|
||||
* Calls <code>readNodeFromFile()</code> which recursively reads all nodes.
|
||||
*/
|
||||
int readFromFile(std::ifstream& inFileStream, bool readData,
|
||||
const std::string& folderPath = std::string());
|
||||
|
||||
/**
|
||||
* Write specified part of Octree to multiple files, including all data.
|
||||
* \param branchIndex defines which branch to write.
|
||||
* Clears specified branch after writing is done.
|
||||
* Calls <code>writeNodeToMultipleFiles()</code> for the specified branch.
|
||||
*/
|
||||
void writeToMultipleFiles(const std::string& outFolderPath, size_t branchIndex);
|
||||
|
||||
/**
|
||||
* Getters.
|
||||
*/
|
||||
size_t numLeafNodes() const;
|
||||
size_t numInnerNodes() const;
|
||||
size_t totalNodes() const;
|
||||
size_t totalDepth() const;
|
||||
size_t maxDist() const;
|
||||
size_t maxStarsPerNode() const;
|
||||
size_t biggestChunkIndexInUse() const;
|
||||
size_t numFreeSpotsInBuffer() const;
|
||||
bool isRebuildOngoing() const;
|
||||
|
||||
/**
|
||||
* \returns current CPU RAM budget in bytes.
|
||||
*/
|
||||
long long cpuRamBudget() const;
|
||||
|
||||
private:
|
||||
const size_t POS_SIZE = 3;
|
||||
const size_t COL_SIZE = 2;
|
||||
const size_t VEL_SIZE = 3;
|
||||
|
||||
// MAX_DIST [kPc] - Determines the depth of Octree together with MAX_STARS_PER_NODE.
|
||||
// A smaller distance is better (i.e. a smaller total depth) and a smaller MAX_STARS
|
||||
// is also better (i.e. finer borders and fewer nodes/less data needs to be uploaded
|
||||
// to the GPU), but MAX_STARS still needs to be big enough to be able to swallow all
|
||||
// stars that falls outside of top border nodes, otherwise it causes a stack overflow
|
||||
// when building Octree. However, fewer total nodes (i.e. bigger Stars/Node) reduces
|
||||
// traversing time which is preferable, especially with big datasets
|
||||
// DR1_TGAS [2M] - A MAX_DIST of 5 kPc works fine with down to 1 kSPN.
|
||||
// DR1_full [1.2B] - A MAX_DIST of 10 kPc works fine with most SPN.
|
||||
// DR2_rv [7.2M] - A MAX_DIST of 15 kPc works fine with down to 10 kSPN.
|
||||
// DR2_subset [42.9M] - A MAX_DIST of 100 kPc works fine with 20 kSPN.
|
||||
// DR2_full [1.7B] - A MAX_DIST of 250 kPc works fine with 150 kSPN.
|
||||
size_t MAX_DIST = 2; // [kPc]
|
||||
size_t MAX_STARS_PER_NODE = 2000;
|
||||
|
||||
const int DEFAULT_INDEX = -1;
|
||||
const std::string BINARY_SUFFIX = ".bin";
|
||||
|
||||
/**
|
||||
* \returns the correct index of child node. Maps [1,1,1] to 0 and [-1,-1,-1] to 7.
|
||||
*/
|
||||
size_t getChildIndex(float posX, float posY, float posZ, float origX = 0.f,
|
||||
float origY = 0.f, float origZ = 0.f);
|
||||
|
||||
/**
|
||||
* Private help function for <code>insert()</code>. Inserts star into node if leaf and
|
||||
* numStars < MAX_STARS_PER_NODE. If a leaf goes above the threshold it is subdivided
|
||||
* into 8 new nodes.
|
||||
* If node is an inner node, then star is stores in LOD cache if it is among the
|
||||
* brightest stars in all children.
|
||||
*/
|
||||
bool insertInNode(OctreeNode& node, const std::vector<float>& starValues,
|
||||
int depth = 1);
|
||||
|
||||
/**
|
||||
* Slices LOD cache data in node to the MAX_STARS_PER_NODE brightest stars. This needs
|
||||
* to be called after the last star has been inserted into Octree but before it is
|
||||
* saved to file(s). Slices all descendants recursively.
|
||||
*/
|
||||
void sliceNodeLodCache(OctreeNode& node);
|
||||
|
||||
/**
|
||||
* Private help function for <code>insertInNode()</code>. Stores star data in node and
|
||||
* keeps track of the brightest stars all children.
|
||||
*/
|
||||
void storeStarData(OctreeNode& node, const std::vector<float>& starValues);
|
||||
|
||||
/**
|
||||
* Private help function for <code>printStarsPerNode()</code>. \returns an accumulated
|
||||
* string containing all descendant nodes.
|
||||
*/
|
||||
std::string printStarsPerNode(const OctreeNode& node,
|
||||
const std::string& prefix) const;
|
||||
|
||||
/**
|
||||
* Private help function for <code>traverseData()</code>. Recursively checks which
|
||||
* nodes intersect with the view frustum (interpreted as an AABB) and decides if data
|
||||
* should be optimized away or not. Keeps track of which nodes that are visible and
|
||||
* loaded (if streaming). \param deltaStars keeps track of how many stars that were
|
||||
* added/removed this render call.
|
||||
*/
|
||||
std::map<int, std::vector<float>> checkNodeIntersection(OctreeNode& node,
|
||||
const glm::dmat4& mvp, const glm::vec2& screenSize, int& deltaStars,
|
||||
gaia::RenderOption option);
|
||||
|
||||
/**
|
||||
* Checks if specified node existed in cache, and removes it if that's the case.
|
||||
* If node is an inner node then all children will be checked recursively as well as
|
||||
* long as \param recursive is not set to false. \param deltaStars keeps track of how
|
||||
* many stars that were removed.
|
||||
*/
|
||||
std::map<int, std::vector<float>> removeNodeFromCache(OctreeNode& node,
|
||||
int& deltaStars, bool recursive = true);
|
||||
|
||||
/**
|
||||
* Get data in node and its descendants regardless if they are visible or not.
|
||||
*/
|
||||
std::vector<float> getNodeData(const OctreeNode& node, gaia::RenderOption option);
|
||||
|
||||
/**
|
||||
* Clear data from node and its descendants and shrink vectors to deallocate memory.
|
||||
*/
|
||||
void clearNodeData(OctreeNode& node);
|
||||
|
||||
/**
|
||||
* Contruct default children nodes for specified node.
|
||||
*/
|
||||
void createNodeChildren(OctreeNode& node);
|
||||
|
||||
/**
|
||||
* Checks if node should be inserted into stream or not. \returns true if it should,
|
||||
* (i.e. it doesn't already exists, there is room for it in the buffer and node data
|
||||
* is loaded if streaming). \returns false otherwise.
|
||||
*/
|
||||
bool updateBufferIndex(OctreeNode& node);
|
||||
|
||||
/**
|
||||
* Node should be inserted into stream. This function \returns the data to be
|
||||
* inserted. If VBOs are used then the chunks will be appended by zeros, otherwise
|
||||
* only the star data corresponding to RenderOption \param option will be inserted.
|
||||
*
|
||||
* \param deltaStars keeps track of how many stars that were added.
|
||||
*/
|
||||
std::vector<float> constructInsertData(const OctreeNode& node,
|
||||
gaia::RenderOption option, int& deltaStars);
|
||||
|
||||
/**
|
||||
* Write a node to outFileStream. \param writeData defines if data should be included
|
||||
* or if only structure should be written.
|
||||
*/
|
||||
void writeNodeToFile(std::ofstream& outFileStream, const OctreeNode& node,
|
||||
bool writeData);
|
||||
|
||||
/**
|
||||
* Read a node from file and its potential children. \param readData defines if full
|
||||
* data or only structure should be read.
|
||||
* \returns accumulated sum of all read stars in node and its descendants.
|
||||
*/
|
||||
int readNodeFromFile(std::ifstream& inFileStream, OctreeNode& node, bool readData);
|
||||
|
||||
/**
|
||||
* Write node data to a file. \param outFilePrefix specifies the accumulated path
|
||||
* and name of the file. If \param threadWrites is set to true then one new thread
|
||||
* will be created for each child to write its descendents.
|
||||
*/
|
||||
void writeNodeToMultipleFiles(const std::string& outFilePrefix, OctreeNode& node,
|
||||
bool threadWrites);
|
||||
|
||||
/**
|
||||
* Finds the neighboring node on the same level (or a higher level if there is no
|
||||
* corresponding level) in the specified direction. Also fetches data from found node
|
||||
* if it's not already loaded. \param additionalLevelsToFetch determines if any
|
||||
* descendants of the found node should be fetched as well (if they exists).
|
||||
*/
|
||||
void findAndFetchNeighborNode(unsigned long long firstParentId, int x, int y, int z,
|
||||
int additionalLevelsToFetch);
|
||||
|
||||
/**
|
||||
* Fetches data from all children of \param parentNode, as long as it's not already
|
||||
* fetched, it exists and it can fit in RAM.
|
||||
* \param additionalLevelsToFetch determines how many levels of descendants to fetch.
|
||||
* If it is set to 0 no additional level will be fetched.
|
||||
* If it is set to a negative value then all descendants will be fetched recursively.
|
||||
* Calls <code>fetchNodeDataFromFile()</code> for every child that passes the tests.
|
||||
*/
|
||||
void fetchChildrenNodes(OctreeNode& parentNode, int additionalLevelsToFetch);
|
||||
|
||||
/**
|
||||
* Fetches data for specified node from file.
|
||||
* OBS! Only call if node file exists (i.e. node has any data, node->numStars > 0)
|
||||
* and is not already loaded.
|
||||
*/
|
||||
void fetchNodeDataFromFile(OctreeNode& node);
|
||||
|
||||
/**
|
||||
* Loops though all nodes in \param nodesToRemove and clears them from RAM.
|
||||
* Also checks if any ancestor should change the <code>hasLoadedDescendant</code> flag
|
||||
* by calling <code>propagateUnloadedNodes()</code> with all ancestors.
|
||||
*/
|
||||
void removeNodesFromRam(const std::vector<unsigned long long>& nodesToRemove);
|
||||
|
||||
/**
|
||||
* Removes data in specified node from main memory and updates RAM budget and flags
|
||||
* accordingly.
|
||||
*/
|
||||
void removeNode(OctreeNode& node);
|
||||
|
||||
/**
|
||||
* Loops through \param ancestorNodes backwards and checks if parent node has any
|
||||
* loaded descendants left. If not, then flag <code>hasLoadedDescendant</code> will be
|
||||
* set to false for that parent node and next parent in line will be checked.
|
||||
*/
|
||||
void propagateUnloadedNodes(std::vector<std::shared_ptr<OctreeNode>> ancestorNodes);
|
||||
|
||||
std::shared_ptr<OctreeNode> _root;
|
||||
std::unique_ptr<OctreeCuller> _culler;
|
||||
std::stack<int> _freeSpotsInBuffer;
|
||||
std::set<int> _removedKeysInPrevCall;
|
||||
std::queue<unsigned long long> _leastRecentlyFetchedNodes;
|
||||
std::mutex _leastRecentlyFetchedNodesMutex;
|
||||
|
||||
size_t _totalDepth = 0;
|
||||
size_t _numLeafNodes = 0;
|
||||
size_t _numInnerNodes = 0;
|
||||
size_t _biggestChunkIndexInUse = 0;
|
||||
size_t _valuesPerStar = 0;
|
||||
float _minTotalPixelsLod = 0.f;
|
||||
|
||||
size_t _maxStackSize = 0;
|
||||
bool _rebuildBuffer = false;
|
||||
bool _useVBO = false;
|
||||
bool _streamOctree = false;
|
||||
bool _datasetFitInMemory = false;
|
||||
long long _cpuRamBudget = 0;
|
||||
long long _maxCpuRamBudget = 0;
|
||||
unsigned long long _parentNodeOfCamera = 8;
|
||||
std::string _streamFolderPath;
|
||||
size_t _traversedBranchesInRenderCall = 0;
|
||||
|
||||
}; // class OctreeManager
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
#endif // __OPENSPACE_MODULE_GAIA___OCTREEMANAGER___H__
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,216 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2020 *
|
||||
* *
|
||||
* 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_MODULE_GAIA___RENDERABLEGAIASTARS___H__
|
||||
#define __OPENSPACE_MODULE_GAIA___RENDERABLEGAIASTARS___H__
|
||||
|
||||
#include <openspace/rendering/renderable.h>
|
||||
|
||||
#include <modules/gaia/rendering/octreemanager.h>
|
||||
#include <openspace/properties/optionproperty.h>
|
||||
#include <openspace/properties/stringlistproperty.h>
|
||||
#include <openspace/properties/stringproperty.h>
|
||||
#include <openspace/properties/scalar/boolproperty.h>
|
||||
#include <openspace/properties/scalar/floatproperty.h>
|
||||
#include <openspace/properties/scalar/intproperty.h>
|
||||
#include <openspace/properties/vector/vec2property.h>
|
||||
#include <openspace/properties/vector/ivec2property.h>
|
||||
#include <ghoul/opengl/bufferbinding.h>
|
||||
#include <ghoul/opengl/ghoul_gl.h>
|
||||
#include <ghoul/opengl/uniformcache.h>
|
||||
|
||||
namespace ghoul::filesystem { class File; }
|
||||
namespace ghoul::opengl {
|
||||
class ProgramObject;
|
||||
class Texture;
|
||||
} // namespace ghoul::opengl
|
||||
|
||||
namespace openspace {
|
||||
|
||||
namespace documentation { struct Documentation; }
|
||||
|
||||
class RenderableGaiaStars : public Renderable {
|
||||
public:
|
||||
explicit RenderableGaiaStars(const ghoul::Dictionary& dictionary);
|
||||
virtual ~RenderableGaiaStars() = default;
|
||||
|
||||
void initializeGL() override;
|
||||
void deinitializeGL() override;
|
||||
|
||||
bool isReady() const override;
|
||||
|
||||
void render(const RenderData& data, RendererTasks& rendererTask) override;
|
||||
void update(const UpdateData& data) override;
|
||||
|
||||
static documentation::Documentation Documentation();
|
||||
|
||||
private:
|
||||
/**
|
||||
* Reads data file in format defined by FileReaderOption.
|
||||
*
|
||||
* \return true if data was successfully read.
|
||||
*/
|
||||
bool readDataFile();
|
||||
|
||||
/**
|
||||
* Reads a FITS file by using FitsFileReader.readFitsFile() and constructs an octree.
|
||||
*
|
||||
* \return the number of stars read.
|
||||
*/
|
||||
int readFitsFile(const std::string& filePath);
|
||||
|
||||
/**
|
||||
* Read a SPECK file by using FitsFileReader.readSpeckFile() and constructs an octree.
|
||||
*
|
||||
* \return the number of stars read.
|
||||
*/
|
||||
int readSpeckFile(const std::string& filePath);
|
||||
|
||||
/**
|
||||
* Reads a preprocessed binary file and constructs an octree.
|
||||
*
|
||||
* \return the number of stars read.
|
||||
*/
|
||||
int readBinaryRawFile(const std::string& filePath);
|
||||
|
||||
/**
|
||||
* Reads a pre-constructed octree, with all data, from a binary file.
|
||||
*
|
||||
* \return the number of stars read.
|
||||
*/
|
||||
int readBinaryOctreeFile(const std::string& filePath);
|
||||
|
||||
/**
|
||||
* Reads the structure of a pre-constructed octree from a binary file, without any
|
||||
* data.
|
||||
*
|
||||
* \return the number of stars read.
|
||||
*/
|
||||
int readBinaryOctreeStructureFile(const std::string& folderPath);
|
||||
|
||||
/**
|
||||
* Checks for any OpenGL errors and reports these to the log if _reportGlErrors is
|
||||
* set to true.
|
||||
*/
|
||||
void checkGlErrors(const std::string& identifier) const;
|
||||
|
||||
properties::StringProperty _filePath;
|
||||
std::unique_ptr<ghoul::filesystem::File> _dataFile;
|
||||
bool _dataIsDirty = true;
|
||||
bool _buffersAreDirty = true;
|
||||
bool _shadersAreDirty = false;
|
||||
|
||||
properties::StringProperty _pointSpreadFunctionTexturePath;
|
||||
std::unique_ptr<ghoul::opengl::Texture> _pointSpreadFunctionTexture;
|
||||
std::unique_ptr<ghoul::filesystem::File> _pointSpreadFunctionFile;
|
||||
bool _pointSpreadFunctionTextureIsDirty = true;
|
||||
|
||||
properties::StringProperty _colorTexturePath;
|
||||
std::unique_ptr<ghoul::opengl::Texture> _colorTexture;
|
||||
std::unique_ptr<ghoul::filesystem::File> _colorTextureFile;
|
||||
bool _colorTextureIsDirty = true;
|
||||
|
||||
properties::FloatProperty _luminosityMultiplier;
|
||||
properties::FloatProperty _magnitudeBoost;
|
||||
properties::FloatProperty _cutOffThreshold;
|
||||
properties::FloatProperty _sharpness;
|
||||
properties::FloatProperty _billboardSize;
|
||||
properties::FloatProperty _closeUpBoostDist;
|
||||
properties::IntProperty _tmPointFilterSize;
|
||||
properties::FloatProperty _tmPointSigma;
|
||||
properties::IVec2Property _additionalNodes;
|
||||
properties::FloatProperty _tmPointPixelWeightThreshold;
|
||||
properties::FloatProperty _lodPixelThreshold;
|
||||
|
||||
properties::Vec2Property _posXThreshold;
|
||||
properties::Vec2Property _posYThreshold;
|
||||
properties::Vec2Property _posZThreshold;
|
||||
properties::Vec2Property _gMagThreshold;
|
||||
properties::Vec2Property _bpRpThreshold;
|
||||
properties::Vec2Property _distThreshold;
|
||||
|
||||
properties::IntProperty _firstRow;
|
||||
properties::IntProperty _lastRow;
|
||||
properties::StringListProperty _columnNamesList;
|
||||
std::vector<std::string> _columnNames;
|
||||
properties::OptionProperty _fileReaderOption;
|
||||
properties::OptionProperty _renderOption;
|
||||
properties::OptionProperty _shaderOption;
|
||||
properties::IntProperty _nRenderedStars;
|
||||
// LongLongProperty doesn't show up in menu, use FloatProperty instead.
|
||||
properties::FloatProperty _cpuRamBudgetProperty;
|
||||
properties::FloatProperty _gpuStreamBudgetProperty;
|
||||
properties::FloatProperty _maxGpuMemoryPercent;
|
||||
properties::FloatProperty _maxCpuMemoryPercent;
|
||||
|
||||
properties::BoolProperty _reportGlErrors;
|
||||
|
||||
std::unique_ptr<ghoul::opengl::ProgramObject> _program;
|
||||
UniformCache(model, view, cameraPos, cameraLookUp, viewScaling, projection,
|
||||
renderOption, luminosityMultiplier, magnitudeBoost, cutOffThreshold,
|
||||
sharpness, billboardSize, closeUpBoostDist, screenSize, psfTexture,
|
||||
time, colorTexture, nChunksToRender, valuesPerStar, maxStarsPerNode)
|
||||
_uniformCache;
|
||||
|
||||
UniformCache(posXThreshold, posYThreshold, posZThreshold, gMagThreshold,
|
||||
bpRpThreshold, distThreshold) _uniformFilterCache;
|
||||
|
||||
std::unique_ptr<ghoul::opengl::ProgramObject> _programTM;
|
||||
UniformCache(renderedTexture, screenSize, filterSize, sigma, pixelWeightThreshold,
|
||||
projection) _uniformCacheTM;
|
||||
std::unique_ptr<ghoul::opengl::Texture> _fboTexture;
|
||||
|
||||
OctreeManager _octreeManager;
|
||||
std::unique_ptr<ghoul::opengl::BufferBinding<
|
||||
ghoul::opengl::bufferbinding::Buffer::ShaderStorage>> _ssboIdxBinding;
|
||||
std::unique_ptr<ghoul::opengl::BufferBinding<
|
||||
ghoul::opengl::bufferbinding::Buffer::ShaderStorage>> _ssboDataBinding;
|
||||
|
||||
std::vector<int> _accumulatedIndices;
|
||||
size_t _nRenderValuesPerStar = 0;
|
||||
int _nStarsToRender = 0;
|
||||
bool _firstDrawCalls = true;
|
||||
glm::dquat _previousCameraRotation = glm::dquat(1.0, 0.0, 0.0, 0.0);
|
||||
bool _useVBO = false;
|
||||
long long _cpuRamBudgetInBytes = 0;
|
||||
long long _totalDatasetSizeInBytes = 0;
|
||||
long long _gpuMemoryBudgetInBytes = 0;
|
||||
long long _maxStreamingBudgetInBytes = 0;
|
||||
size_t _chunkSize = 0;
|
||||
|
||||
GLuint _vao = 0;
|
||||
GLuint _vaoEmpty = 0;
|
||||
GLuint _vboPos = 0;
|
||||
GLuint _vboCol = 0;
|
||||
GLuint _vboVel = 0;
|
||||
GLuint _ssboIdx = 0;
|
||||
GLuint _ssboData = 0;
|
||||
GLuint _vaoQuad = 0;
|
||||
GLuint _vboQuad = 0;
|
||||
GLuint _fbo = 0;
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
#endif // __OPENSPACE_MODULE_GAIA___RENDERABLEGAIASTARS___H__
|
||||
@@ -1,892 +0,0 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2020 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
|
||||
* software and associated documentation files (the "Software"), to deal in the Software *
|
||||
* without restriction, including without limitation the rights to use, copy, modify, *
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
|
||||
* permit persons to whom the Software is furnished to do so, subject to the following *
|
||||
* conditions: *
|
||||
* *
|
||||
* The above copyright notice and this permission notice shall be included in all copies *
|
||||
* or substantial portions of the Software. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#include <modules/galaxy/rendering/renderablegalaxy.h>
|
||||
|
||||
#include <modules/galaxy/rendering/galaxyraycaster.h>
|
||||
#include <modules/volume/rawvolume.h>
|
||||
#include <modules/volume/rawvolumereader.h>
|
||||
#include <openspace/engine/globals.h>
|
||||
#include <openspace/rendering/raycastermanager.h>
|
||||
#include <openspace/rendering/renderable.h>
|
||||
#include <openspace/rendering/renderengine.h>
|
||||
#include <openspace/util/boxgeometry.h>
|
||||
#include <openspace/util/distanceconstants.h>
|
||||
#include <openspace/util/updatestructures.h>
|
||||
#include <ghoul/fmt.h>
|
||||
#include <ghoul/glm.h>
|
||||
#include <ghoul/filesystem/cachemanager.h>
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <ghoul/io/texture/texturereader.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/opengl/ghoul_gl.h>
|
||||
#include <ghoul/opengl/programobject.h>
|
||||
#include <ghoul/opengl/texture.h>
|
||||
#include <ghoul/opengl/textureunit.h>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <fstream>
|
||||
|
||||
namespace {
|
||||
constexpr int8_t CurrentCacheVersion = 1;
|
||||
|
||||
constexpr const char* GlslRaycastPath =
|
||||
"${MODULE_GALAXY}/shaders/galaxyraycast.glsl";
|
||||
constexpr const char* GlslBoundsVsPath =
|
||||
"${MODULE_GALAXY}/shaders/raycasterbounds_vs.glsl";
|
||||
constexpr const char* GlslBoundsFsPath =
|
||||
"${MODULE_GALAXY}/shaders/raycasterbounds_fs.glsl";
|
||||
constexpr const char* _loggerCat = "Renderable Galaxy";
|
||||
|
||||
constexpr const std::array<const char*, 4> UniformNamesPoints = {
|
||||
"modelMatrix", "cameraViewProjectionMatrix", "eyePosition",
|
||||
"opacityCoefficient"
|
||||
};
|
||||
|
||||
constexpr const std::array<const char*, 5> UniformNamesBillboards = {
|
||||
"modelMatrix", "cameraViewProjectionMatrix",
|
||||
"cameraUp", "eyePosition", "psfTexture"
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo VolumeRenderingEnabledInfo = {
|
||||
"VolumeRenderingEnabled",
|
||||
"Volume Rendering",
|
||||
"" // @TODO Missing documentation
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo StarRenderingEnabledInfo = {
|
||||
"StarRenderingEnabled",
|
||||
"Star Rendering",
|
||||
"" // @TODO Missing documentation
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo StepSizeInfo = {
|
||||
"StepSize",
|
||||
"Step Size",
|
||||
"" // @TODO Missing documentation
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo AbsorptionMultiplyInfo = {
|
||||
"AbsorptionMultiply",
|
||||
"Absorption Multiplier",
|
||||
"" // @TODO Missing documentation
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo EmissionMultiplyInfo = {
|
||||
"EmissionMultiply",
|
||||
"Emission Multiplier",
|
||||
"" // @TODO Missing documentation
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo TranslationInfo = {
|
||||
"Translation",
|
||||
"Translation",
|
||||
"" // @TODO Missing documentation
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo RotationInfo = {
|
||||
"Rotation",
|
||||
"Euler rotation",
|
||||
"" // @TODO Missing documentation
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo StarRenderingMethodInfo = {
|
||||
"StarRenderingMethod",
|
||||
"Star Rendering Method",
|
||||
"This value determines which rendering method is used for visualization of the "
|
||||
"stars."
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo EnabledPointsRatioInfo = {
|
||||
"EnabledPointsRatio",
|
||||
"Enabled points",
|
||||
"" // @TODO Missing documentation
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo DownscaleVolumeRenderingInfo =
|
||||
{
|
||||
"Downscale",
|
||||
"Downscale Factor Volume Rendering",
|
||||
"This value set the downscaling factor"
|
||||
" when rendering the current volume."
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo NumberOfRayCastingStepsInfo =
|
||||
{
|
||||
"Steps",
|
||||
"Number of RayCasting Steps",
|
||||
"This value set the number of integration steps during the raycasting procedure."
|
||||
};
|
||||
|
||||
void saveCachedFile(const std::string& file, const std::vector<glm::vec3>& positions,
|
||||
const std::vector<glm::vec3>& colors, int64_t nPoints,
|
||||
float pointsRatio)
|
||||
{
|
||||
std::ofstream fileStream(file, std::ofstream::binary);
|
||||
|
||||
if (!fileStream.good()) {
|
||||
LERROR(fmt::format("Error opening file '{}' for save cache file", file));
|
||||
return;
|
||||
}
|
||||
|
||||
fileStream.write(
|
||||
reinterpret_cast<const char*>(&CurrentCacheVersion),
|
||||
sizeof(int8_t)
|
||||
);
|
||||
fileStream.write(reinterpret_cast<const char*>(&nPoints), sizeof(int64_t));
|
||||
fileStream.write(reinterpret_cast<const char*>(&pointsRatio), sizeof(float));
|
||||
uint64_t nPositions = static_cast<uint64_t>(positions.size());
|
||||
fileStream.write(reinterpret_cast<const char*>(&nPositions), sizeof(uint64_t));
|
||||
fileStream.write(
|
||||
reinterpret_cast<const char*>(positions.data()),
|
||||
positions.size() * sizeof(glm::vec3)
|
||||
);
|
||||
uint64_t nColors = static_cast<uint64_t>(colors.size());
|
||||
fileStream.write(reinterpret_cast<const char*>(&nColors), sizeof(uint64_t));
|
||||
fileStream.write(
|
||||
reinterpret_cast<const char*>(colors.data()),
|
||||
colors.size() * sizeof(glm::vec3)
|
||||
);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
RenderableGalaxy::RenderableGalaxy(const ghoul::Dictionary& dictionary)
|
||||
: Renderable(dictionary)
|
||||
, _volumeRenderingEnabled(VolumeRenderingEnabledInfo, true)
|
||||
, _starRenderingEnabled(StarRenderingEnabledInfo, true)
|
||||
, _stepSize(StepSizeInfo, 0.01f, 0.0005f, 0.05f, 0.001f)
|
||||
, _absorptionMultiply(AbsorptionMultiplyInfo, 40.f, 0.0f, 200.0f)
|
||||
, _emissionMultiply(EmissionMultiplyInfo, 200.f, 0.0f, 1000.0f)
|
||||
, _starRenderingMethod(
|
||||
StarRenderingMethodInfo,
|
||||
properties::OptionProperty::DisplayType::Dropdown
|
||||
)
|
||||
, _enabledPointsRatio(EnabledPointsRatioInfo, 0.5f, 0.01f, 1.0f)
|
||||
, _translation(TranslationInfo, glm::vec3(0.f), glm::vec3(0.f), glm::vec3(1.f))
|
||||
, _rotation(
|
||||
RotationInfo,
|
||||
glm::vec3(0.f),
|
||||
glm::vec3(0.f),
|
||||
glm::vec3(glm::two_pi<float>())
|
||||
)
|
||||
, _downScaleVolumeRendering(DownscaleVolumeRenderingInfo, 1.f, 0.1f, 1.f)
|
||||
, _numberOfRayCastingSteps(NumberOfRayCastingStepsInfo, 1000.f, 1.f, 1000.f)
|
||||
{
|
||||
dictionary.getValue("VolumeRenderingEnabled", _volumeRenderingEnabled);
|
||||
dictionary.getValue("StarRenderingEnabled", _starRenderingEnabled);
|
||||
dictionary.getValue("StepSize", _stepSize);
|
||||
dictionary.getValue("AbsorptionMultiply", _absorptionMultiply);
|
||||
dictionary.getValue("EmissionMultiply", _emissionMultiply);
|
||||
dictionary.getValue("StarRenderingMethod", _starRenderingMethod);
|
||||
dictionary.getValue("EnabledPointsRatio", _enabledPointsRatio);
|
||||
dictionary.getValue("Translation", _translation);
|
||||
dictionary.getValue("Rotation", _rotation);
|
||||
|
||||
if (dictionary.hasKeyAndValue<bool>(VolumeRenderingEnabledInfo.identifier)) {
|
||||
_volumeRenderingEnabled = dictionary.value<bool>(
|
||||
VolumeRenderingEnabledInfo.identifier
|
||||
);
|
||||
}
|
||||
|
||||
if (dictionary.hasKeyAndValue<bool>(StarRenderingEnabledInfo.identifier)) {
|
||||
_starRenderingEnabled = static_cast<bool>(StarRenderingEnabledInfo.identifier);
|
||||
}
|
||||
|
||||
if (dictionary.hasKeyAndValue<double>(StepSizeInfo.identifier)) {
|
||||
_stepSize = static_cast<float>(dictionary.value<double>(StepSizeInfo.identifier));
|
||||
}
|
||||
|
||||
if (dictionary.hasKeyAndValue<double>(AbsorptionMultiplyInfo.identifier)) {
|
||||
_absorptionMultiply = static_cast<float>(
|
||||
dictionary.value<double>(AbsorptionMultiplyInfo.identifier)
|
||||
);
|
||||
}
|
||||
|
||||
if (dictionary.hasKeyAndValue<double>(EmissionMultiplyInfo.identifier)) {
|
||||
_emissionMultiply = static_cast<float>(
|
||||
dictionary.value<double>(EmissionMultiplyInfo.identifier)
|
||||
);
|
||||
}
|
||||
|
||||
_starRenderingMethod.addOptions({
|
||||
{ 0, "Points" },
|
||||
{ 1, "Billboards" }
|
||||
});
|
||||
if (dictionary.hasKey(StarRenderingMethodInfo.identifier)) {
|
||||
const std::string starRenderingMethod = dictionary.value<std::string>(
|
||||
StarRenderingMethodInfo.identifier
|
||||
);
|
||||
if (starRenderingMethod == "Points") {
|
||||
_starRenderingMethod = 0;
|
||||
}
|
||||
else if (starRenderingMethod == "Billboards") {
|
||||
_starRenderingMethod = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (dictionary.hasKeyAndValue<glm::vec3>(TranslationInfo.identifier)) {
|
||||
_translation = dictionary.value<glm::vec3>(TranslationInfo.identifier);
|
||||
}
|
||||
|
||||
if (dictionary.hasKeyAndValue<glm::vec3>(RotationInfo.identifier)) {
|
||||
_rotation = dictionary.value<glm::vec3>(RotationInfo.identifier);
|
||||
}
|
||||
|
||||
if (!dictionary.hasKeyAndValue<ghoul::Dictionary>("Volume")) {
|
||||
LERROR("No volume dictionary specified.");
|
||||
}
|
||||
|
||||
ghoul::Dictionary volumeDictionary = dictionary.value<ghoul::Dictionary>("Volume");
|
||||
|
||||
std::string volumeFilename;
|
||||
if (volumeDictionary.getValue("Filename", volumeFilename)) {
|
||||
_volumeFilename = absPath(volumeFilename);
|
||||
}
|
||||
else {
|
||||
LERROR("No volume filename specified.");
|
||||
}
|
||||
glm::vec3 volumeDimensions = glm::vec3(0.f);
|
||||
if (volumeDictionary.getValue("Dimensions", volumeDimensions)) {
|
||||
_volumeDimensions = static_cast<glm::ivec3>(volumeDimensions);
|
||||
}
|
||||
else {
|
||||
LERROR("No volume dimensions specified.");
|
||||
}
|
||||
glm::vec3 volumeSize = glm::vec3(0.f);
|
||||
if (volumeDictionary.getValue("Size", volumeSize)) {
|
||||
_volumeSize = volumeSize;
|
||||
}
|
||||
else {
|
||||
LERROR("No volume dimensions specified.");
|
||||
}
|
||||
|
||||
if (volumeDictionary.hasKey(NumberOfRayCastingStepsInfo.identifier)) {
|
||||
_numberOfRayCastingSteps = static_cast<float>(
|
||||
volumeDictionary.value<double>(NumberOfRayCastingStepsInfo.identifier)
|
||||
);
|
||||
}
|
||||
else {
|
||||
LINFO("Number of raycasting steps not specified. Using default value.");
|
||||
}
|
||||
|
||||
_downScaleVolumeRendering.setVisibility(properties::Property::Visibility::Developer);
|
||||
if (volumeDictionary.hasKey(DownscaleVolumeRenderingInfo.identifier)) {
|
||||
_downScaleVolumeRendering =
|
||||
volumeDictionary.value<float>(DownscaleVolumeRenderingInfo.identifier);
|
||||
}
|
||||
|
||||
if (!dictionary.hasKeyAndValue<ghoul::Dictionary>("Points")) {
|
||||
LERROR("No points dictionary specified.");
|
||||
}
|
||||
|
||||
ghoul::Dictionary pointsDictionary = dictionary.value<ghoul::Dictionary>("Points");
|
||||
std::string pointsFilename;
|
||||
if (pointsDictionary.getValue("Filename", pointsFilename)) {
|
||||
_pointsFilename = absPath(pointsFilename);
|
||||
}
|
||||
else {
|
||||
LERROR("No points filename specified.");
|
||||
}
|
||||
|
||||
if (pointsDictionary.hasKeyAndValue<double>(EnabledPointsRatioInfo.identifier)) {
|
||||
_enabledPointsRatio = static_cast<float>(
|
||||
pointsDictionary.value<double>(EnabledPointsRatioInfo.identifier)
|
||||
);
|
||||
}
|
||||
|
||||
std::string pointSpreadFunctionTexturePath;
|
||||
if (pointsDictionary.getValue("Texture", pointSpreadFunctionTexturePath)) {
|
||||
_pointSpreadFunctionTexturePath = absPath(pointSpreadFunctionTexturePath);
|
||||
_pointSpreadFunctionFile = std::make_unique<ghoul::filesystem::File>(
|
||||
_pointSpreadFunctionTexturePath
|
||||
);
|
||||
}
|
||||
else {
|
||||
LERROR("No points filename specified.");
|
||||
}
|
||||
}
|
||||
|
||||
void RenderableGalaxy::initializeGL() {
|
||||
// Aspect is currently hardcoded to cubic voxels.
|
||||
_aspect = static_cast<glm::vec3>(_volumeDimensions);
|
||||
_aspect /= std::max(std::max(_aspect.x, _aspect.y), _aspect.z);
|
||||
|
||||
// The volume
|
||||
volume::RawVolumeReader<glm::tvec4<GLubyte>> reader(
|
||||
_volumeFilename,
|
||||
_volumeDimensions
|
||||
);
|
||||
_volume = reader.read();
|
||||
|
||||
_texture = std::make_unique<ghoul::opengl::Texture>(
|
||||
_volumeDimensions,
|
||||
ghoul::opengl::Texture::Format::RGBA,
|
||||
GL_RGBA,
|
||||
GL_UNSIGNED_BYTE,
|
||||
ghoul::opengl::Texture::FilterMode::Linear,
|
||||
ghoul::opengl::Texture::WrappingMode::ClampToEdge
|
||||
);
|
||||
|
||||
_texture->setPixelData(
|
||||
reinterpret_cast<char*>(_volume->data()),
|
||||
ghoul::opengl::Texture::TakeOwnership::No
|
||||
);
|
||||
|
||||
_texture->setDimensions(_volume->dimensions());
|
||||
_texture->uploadTexture();
|
||||
|
||||
_raycaster = std::make_unique<GalaxyRaycaster>(*_texture);
|
||||
_raycaster->initialize();
|
||||
|
||||
global::raycasterManager.attachRaycaster(*_raycaster);
|
||||
|
||||
auto onChange = [&](bool enabled) {
|
||||
if (enabled) {
|
||||
global::raycasterManager.attachRaycaster(*_raycaster);
|
||||
}
|
||||
else {
|
||||
global::raycasterManager.detachRaycaster(*_raycaster);
|
||||
}
|
||||
};
|
||||
|
||||
onEnabledChange(onChange);
|
||||
|
||||
addProperty(_volumeRenderingEnabled);
|
||||
addProperty(_starRenderingEnabled);
|
||||
addProperty(_stepSize);
|
||||
addProperty(_absorptionMultiply);
|
||||
addProperty(_emissionMultiply);
|
||||
addProperty(_starRenderingMethod);
|
||||
addProperty(_enabledPointsRatio);
|
||||
addProperty(_translation);
|
||||
addProperty(_rotation);
|
||||
addProperty(_downScaleVolumeRendering);
|
||||
addProperty(_numberOfRayCastingSteps);
|
||||
|
||||
// initialize points.
|
||||
if (_pointsFilename.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
_pointsProgram = global::renderEngine.buildRenderProgram(
|
||||
"Galaxy points",
|
||||
absPath("${MODULE_GALAXY}/shaders/points_vs.glsl"),
|
||||
absPath("${MODULE_GALAXY}/shaders/points_fs.glsl")
|
||||
);
|
||||
_billboardsProgram = global::renderEngine.buildRenderProgram(
|
||||
"Galaxy billboard",
|
||||
absPath("${MODULE_GALAXY}/shaders/billboard_vs.glsl"),
|
||||
absPath("${MODULE_GALAXY}/shaders/billboard_fs.glsl"),
|
||||
absPath("${MODULE_GALAXY}/shaders/billboard_ge.glsl")
|
||||
);
|
||||
|
||||
if (!_pointSpreadFunctionTexturePath.empty()) {
|
||||
_pointSpreadFunctionTexture = ghoul::io::TextureReader::ref().loadTexture(
|
||||
absPath(_pointSpreadFunctionTexturePath)
|
||||
);
|
||||
|
||||
if (_pointSpreadFunctionTexture) {
|
||||
LDEBUG(fmt::format(
|
||||
"Loaded texture from '{}'",
|
||||
absPath(_pointSpreadFunctionTexturePath)
|
||||
));
|
||||
_pointSpreadFunctionTexture->uploadTexture();
|
||||
}
|
||||
_pointSpreadFunctionTexture->setFilter(
|
||||
ghoul::opengl::Texture::FilterMode::AnisotropicMipMap
|
||||
);
|
||||
|
||||
_pointSpreadFunctionFile = std::make_unique<ghoul::filesystem::File>(
|
||||
_pointSpreadFunctionTexturePath
|
||||
);
|
||||
}
|
||||
|
||||
ghoul::opengl::updateUniformLocations(
|
||||
*_pointsProgram,
|
||||
_uniformCachePoints,
|
||||
UniformNamesPoints
|
||||
);
|
||||
ghoul::opengl::updateUniformLocations(
|
||||
*_billboardsProgram,
|
||||
_uniformCacheBillboards,
|
||||
UniformNamesBillboards
|
||||
);
|
||||
|
||||
_pointsProgram->setIgnoreUniformLocationError(
|
||||
ghoul::opengl::ProgramObject::IgnoreError::Yes
|
||||
);
|
||||
|
||||
GLint positionAttrib = _pointsProgram->attributeLocation("in_position");
|
||||
GLint colorAttrib = _pointsProgram->attributeLocation("in_color");
|
||||
|
||||
|
||||
std::vector<glm::vec3> pointPositions;
|
||||
std::vector<glm::vec3> pointColors;
|
||||
|
||||
std::string cachedPointsFile = FileSys.cacheManager()->cachedFilename(
|
||||
_pointsFilename,
|
||||
ghoul::filesystem::CacheManager::Persistent::Yes
|
||||
);
|
||||
const bool hasCachedFile = FileSys.fileExists(cachedPointsFile);
|
||||
if (hasCachedFile) {
|
||||
LINFO(fmt::format("Cached file '{}' used for galaxy point file '{}'",
|
||||
cachedPointsFile, _pointsFilename
|
||||
));
|
||||
|
||||
Result res = loadCachedFile(cachedPointsFile);
|
||||
if (res.success) {
|
||||
pointPositions = std::move(res.positions);
|
||||
pointColors = std::move(res.color);
|
||||
}
|
||||
else {
|
||||
FileSys.cacheManager()->removeCacheFile(_pointsFilename);
|
||||
Result resPoint = loadPointFile(_pointsFilename);
|
||||
pointPositions = std::move(resPoint.positions);
|
||||
pointColors = std::move(resPoint.color);
|
||||
saveCachedFile(
|
||||
cachedPointsFile,
|
||||
pointPositions,
|
||||
pointColors,
|
||||
_nPoints,
|
||||
_enabledPointsRatio
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Result res = loadPointFile(_pointsFilename);
|
||||
ghoul_assert(res.success, "Point file loading failed");
|
||||
pointPositions = std::move(res.positions);
|
||||
pointColors = std::move(res.color);
|
||||
saveCachedFile(
|
||||
cachedPointsFile,
|
||||
pointPositions,
|
||||
pointColors,
|
||||
_nPoints,
|
||||
_enabledPointsRatio
|
||||
);
|
||||
}
|
||||
|
||||
glGenVertexArrays(1, &_pointsVao);
|
||||
glGenBuffers(1, &_positionVbo);
|
||||
glGenBuffers(1, &_colorVbo);
|
||||
|
||||
glBindVertexArray(_pointsVao);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, _positionVbo);
|
||||
glBufferData(GL_ARRAY_BUFFER,
|
||||
pointPositions.size() * sizeof(glm::vec3),
|
||||
pointPositions.data(),
|
||||
GL_STATIC_DRAW
|
||||
);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, _colorVbo);
|
||||
glBufferData(GL_ARRAY_BUFFER,
|
||||
pointColors.size() * sizeof(glm::vec3),
|
||||
pointColors.data(),
|
||||
GL_STATIC_DRAW
|
||||
);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, _positionVbo);
|
||||
glEnableVertexAttribArray(positionAttrib);
|
||||
glVertexAttribPointer(positionAttrib, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, _colorVbo);
|
||||
glEnableVertexAttribArray(colorAttrib);
|
||||
glVertexAttribPointer(colorAttrib, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
void RenderableGalaxy::deinitializeGL() {
|
||||
if (_raycaster) {
|
||||
global::raycasterManager.detachRaycaster(*_raycaster);
|
||||
_raycaster = nullptr;
|
||||
}
|
||||
|
||||
glDeleteVertexArrays(1, &_pointsVao);
|
||||
glDeleteBuffers(1, &_positionVbo);
|
||||
glDeleteBuffers(1, &_colorVbo);
|
||||
}
|
||||
|
||||
bool RenderableGalaxy::isReady() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
void RenderableGalaxy::update(const UpdateData& data) {
|
||||
if (!_raycaster) {
|
||||
return;
|
||||
}
|
||||
//glm::mat4 transform = glm::translate(, static_cast<glm::vec3>(_translation));
|
||||
const glm::vec3 eulerRotation = static_cast<glm::vec3>(_rotation);
|
||||
glm::mat4 transform = glm::rotate(
|
||||
glm::mat4(1.f),
|
||||
eulerRotation.x,
|
||||
glm::vec3(1.f, 0.f, 0.f)
|
||||
);
|
||||
transform = glm::rotate(transform, eulerRotation.y, glm::vec3(0.f, 1.f, 0.f));
|
||||
transform = glm::rotate(transform, eulerRotation.z, glm::vec3(0.f, 0.f, 1.f));
|
||||
|
||||
glm::mat4 volumeTransform = glm::scale(transform, _volumeSize);
|
||||
_pointTransform = transform;
|
||||
//_pointTransform = glm::scale(transform, _pointScaling);
|
||||
|
||||
const glm::vec4 translation = glm::vec4(_translation.value()*_volumeSize, 0.f);
|
||||
|
||||
// Todo: handle floating point overflow, to actually support translation.
|
||||
|
||||
volumeTransform[3] += translation;
|
||||
_pointTransform[3] += translation;
|
||||
|
||||
_raycaster->setDownscaleRender(_downScaleVolumeRendering);
|
||||
_raycaster->setMaxSteps(static_cast<int>(_numberOfRayCastingSteps));
|
||||
_raycaster->setStepSize(_stepSize);
|
||||
_raycaster->setAspect(_aspect);
|
||||
_raycaster->setModelTransform(volumeTransform);
|
||||
_raycaster->setAbsorptionMultiplier(_absorptionMultiply);
|
||||
_raycaster->setEmissionMultiplier(_emissionMultiply);
|
||||
_raycaster->setTime(data.time.j2000Seconds());
|
||||
}
|
||||
|
||||
void RenderableGalaxy::render(const RenderData& data, RendererTasks& tasks) {
|
||||
// Render the volume
|
||||
if (_raycaster && _volumeRenderingEnabled) {
|
||||
RaycasterTask task { _raycaster.get(), data };
|
||||
|
||||
const glm::vec3 position = data.camera.positionVec3();
|
||||
const float length = safeLength(position);
|
||||
const glm::vec3 galaxySize = _volumeSize;
|
||||
|
||||
const float maxDim = std::max(std::max(galaxySize.x, galaxySize.y), galaxySize.z);
|
||||
|
||||
const float lowerRampStart = maxDim * 0.01f;
|
||||
const float lowerRampEnd = maxDim * 0.1f;
|
||||
|
||||
const float upperRampStart = maxDim * 2.f;
|
||||
const float upperRampEnd = maxDim * 10.f;
|
||||
|
||||
float opacityCoefficient = 1.f;
|
||||
if (length < lowerRampStart) {
|
||||
opacityCoefficient = 0.f; // camera really close
|
||||
}
|
||||
else if (length < lowerRampEnd) {
|
||||
opacityCoefficient = (length - lowerRampStart) /
|
||||
(lowerRampEnd - lowerRampStart);
|
||||
}
|
||||
else if (length < upperRampStart) {
|
||||
opacityCoefficient = 1.f; // sweet spot (max)
|
||||
}
|
||||
else if (length < upperRampEnd) {
|
||||
opacityCoefficient = 1.f - (length - upperRampStart) /
|
||||
(upperRampEnd - upperRampStart); //fade out
|
||||
}
|
||||
else {
|
||||
opacityCoefficient = 0;
|
||||
}
|
||||
|
||||
_opacityCoefficient = opacityCoefficient;
|
||||
ghoul_assert(
|
||||
_opacityCoefficient >= 0.f && _opacityCoefficient <= 1.f,
|
||||
"Opacity coefficient was not between 0 and 1"
|
||||
);
|
||||
if (opacityCoefficient > 0) {
|
||||
_raycaster->setOpacityCoefficient(_opacityCoefficient);
|
||||
tasks.raycasterTasks.push_back(task);
|
||||
}
|
||||
}
|
||||
|
||||
// Render the stars
|
||||
if (_starRenderingEnabled && _opacityCoefficient > 0.f) {
|
||||
if (_starRenderingMethod == 1) {
|
||||
renderBillboards(data);
|
||||
}
|
||||
else {
|
||||
renderPoints(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RenderableGalaxy::renderPoints(const RenderData& data) {
|
||||
if (!_pointsProgram) {
|
||||
return;
|
||||
}
|
||||
// Saving current OpenGL state
|
||||
GLenum blendEquationRGB;
|
||||
GLenum blendEquationAlpha;
|
||||
GLenum blendDestAlpha;
|
||||
GLenum blendDestRGB;
|
||||
GLenum blendSrcAlpha;
|
||||
GLenum blendSrcRGB;
|
||||
GLboolean depthMask;
|
||||
|
||||
glGetIntegerv(GL_BLEND_EQUATION_RGB, &blendEquationRGB);
|
||||
glGetIntegerv(GL_BLEND_EQUATION_ALPHA, &blendEquationAlpha);
|
||||
glGetIntegerv(GL_BLEND_DST_ALPHA, &blendDestAlpha);
|
||||
glGetIntegerv(GL_BLEND_DST_RGB, &blendDestRGB);
|
||||
glGetIntegerv(GL_BLEND_SRC_ALPHA, &blendSrcAlpha);
|
||||
glGetIntegerv(GL_BLEND_SRC_RGB, &blendSrcRGB);
|
||||
|
||||
glGetBooleanv(GL_DEPTH_WRITEMASK, &depthMask);
|
||||
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
||||
glDepthMask(false);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
_pointsProgram->activate();
|
||||
|
||||
glm::dmat4 rotMatrix = glm::rotate(
|
||||
glm::dmat4(1.0),
|
||||
glm::pi<double>(),
|
||||
glm::dvec3(1.0, 0.0, 0.0)) *
|
||||
glm::rotate(glm::dmat4(1.0), 3.1248, glm::dvec3(0.0, 1.0, 0.0)) *
|
||||
glm::rotate(glm::dmat4(1.0), 4.45741, glm::dvec3(0.0, 0.0, 1.0)
|
||||
);
|
||||
|
||||
glm::dmat4 modelMatrix =
|
||||
glm::translate(glm::dmat4(1.0), data.modelTransform.translation) *
|
||||
glm::dmat4(data.modelTransform.rotation) * rotMatrix *
|
||||
glm::dmat4(glm::scale(glm::dmat4(1.0), glm::dvec3(data.modelTransform.scale)));
|
||||
|
||||
glm::dmat4 projectionMatrix = glm::dmat4(data.camera.projectionMatrix());
|
||||
|
||||
glm::dmat4 cameraViewProjectionMatrix = projectionMatrix *
|
||||
data.camera.combinedViewMatrix();
|
||||
|
||||
_pointsProgram->setUniform(_uniformCachePoints.modelMatrix, modelMatrix);
|
||||
_pointsProgram->setUniform(
|
||||
_uniformCachePoints.cameraViewProjectionMatrix,
|
||||
cameraViewProjectionMatrix
|
||||
);
|
||||
|
||||
glm::dvec3 eyePosition = glm::dvec3(
|
||||
glm::inverse(data.camera.combinedViewMatrix()) *
|
||||
glm::dvec4(0.0, 0.0, 0.0, 1.0)
|
||||
);
|
||||
_pointsProgram->setUniform(_uniformCachePoints.eyePosition, eyePosition);
|
||||
_pointsProgram->setUniform(
|
||||
_uniformCachePoints.opacityCoefficient,
|
||||
_opacityCoefficient
|
||||
);
|
||||
|
||||
glBindVertexArray(_pointsVao);
|
||||
glDrawArrays(GL_POINTS, 0, static_cast<GLsizei>(_nPoints * _enabledPointsRatio));
|
||||
|
||||
glBindVertexArray(0);
|
||||
|
||||
_pointsProgram->deactivate();
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthMask(true);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
// Restores OpenGL blending state
|
||||
glBlendEquationSeparate(blendEquationRGB, blendEquationAlpha);
|
||||
glBlendFuncSeparate(blendSrcRGB, blendDestRGB, blendSrcAlpha, blendDestAlpha);
|
||||
glDepthMask(depthMask);
|
||||
}
|
||||
|
||||
void RenderableGalaxy::renderBillboards(const RenderData& data) {
|
||||
if (!_billboardsProgram) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Saving current OpenGL state
|
||||
GLenum blendEquationRGB;
|
||||
GLenum blendEquationAlpha;
|
||||
GLenum blendDestAlpha;
|
||||
GLenum blendDestRGB;
|
||||
GLenum blendSrcAlpha;
|
||||
GLenum blendSrcRGB;
|
||||
GLboolean depthMask;
|
||||
|
||||
glGetIntegerv(GL_BLEND_EQUATION_RGB, &blendEquationRGB);
|
||||
glGetIntegerv(GL_BLEND_EQUATION_ALPHA, &blendEquationAlpha);
|
||||
glGetIntegerv(GL_BLEND_DST_ALPHA, &blendDestAlpha);
|
||||
glGetIntegerv(GL_BLEND_DST_RGB, &blendDestRGB);
|
||||
glGetIntegerv(GL_BLEND_SRC_ALPHA, &blendSrcAlpha);
|
||||
glGetIntegerv(GL_BLEND_SRC_RGB, &blendSrcRGB);
|
||||
|
||||
glGetBooleanv(GL_DEPTH_WRITEMASK, &depthMask);
|
||||
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
||||
glDepthMask(false);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
_billboardsProgram->activate();
|
||||
|
||||
glm::dmat4 rotMatrix = glm::rotate(
|
||||
glm::dmat4(1.0),
|
||||
glm::pi<double>(),
|
||||
glm::dvec3(1.0, 0.0, 0.0)) *
|
||||
glm::rotate(glm::dmat4(1.0), 3.1248, glm::dvec3(0.0, 1.0, 0.0)) *
|
||||
glm::rotate(glm::dmat4(1.0), 4.45741, glm::dvec3(0.0, 0.0, 1.0)
|
||||
);
|
||||
|
||||
glm::dmat4 modelMatrix =
|
||||
glm::translate(glm::dmat4(1.0), data.modelTransform.translation) *
|
||||
glm::dmat4(data.modelTransform.rotation) * rotMatrix *
|
||||
glm::dmat4(glm::scale(glm::dmat4(1.0), glm::dvec3(data.modelTransform.scale)));
|
||||
|
||||
glm::dmat4 projectionMatrix = glm::dmat4(data.camera.projectionMatrix());
|
||||
|
||||
glm::dmat4 cameraViewProjectionMatrix = projectionMatrix *
|
||||
data.camera.combinedViewMatrix();
|
||||
|
||||
_billboardsProgram->setUniform(_uniformCacheBillboards.modelMatrix, modelMatrix);
|
||||
_billboardsProgram->setUniform(
|
||||
_uniformCacheBillboards.cameraViewProjectionMatrix,
|
||||
cameraViewProjectionMatrix
|
||||
);
|
||||
|
||||
glm::dvec3 eyePosition = glm::dvec3(
|
||||
glm::inverse(data.camera.combinedViewMatrix()) *
|
||||
glm::dvec4(0.0, 0.0, 0.0, 1.0)
|
||||
);
|
||||
_billboardsProgram->setUniform(_uniformCacheBillboards.eyePosition, eyePosition);
|
||||
|
||||
glm::dvec3 cameraUp = data.camera.lookUpVectorWorldSpace();
|
||||
_billboardsProgram->setUniform(_uniformCacheBillboards.cameraUp, cameraUp);
|
||||
|
||||
ghoul::opengl::TextureUnit psfUnit;
|
||||
psfUnit.activate();
|
||||
_pointSpreadFunctionTexture->bind();
|
||||
_billboardsProgram->setUniform(_uniformCacheBillboards.psfTexture, psfUnit);
|
||||
|
||||
glBindVertexArray(_pointsVao);
|
||||
glDrawArrays(GL_POINTS, 0, static_cast<GLsizei>(_nPoints * _enabledPointsRatio));
|
||||
|
||||
glBindVertexArray(0);
|
||||
|
||||
_billboardsProgram->deactivate();
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthMask(true);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
// Restores OpenGL blending state
|
||||
glBlendEquationSeparate(blendEquationRGB, blendEquationAlpha);
|
||||
glBlendFuncSeparate(blendSrcRGB, blendDestRGB, blendSrcAlpha, blendDestAlpha);
|
||||
glDepthMask(depthMask);
|
||||
}
|
||||
|
||||
float RenderableGalaxy::safeLength(const glm::vec3& vector) const {
|
||||
const float maxComponent = std::max(
|
||||
std::max(std::abs(vector.x), std::abs(vector.y)), std::abs(vector.z)
|
||||
);
|
||||
return glm::length(vector / maxComponent) * maxComponent;
|
||||
}
|
||||
|
||||
RenderableGalaxy::Result RenderableGalaxy::loadPointFile(const std::string&) {
|
||||
std::vector<glm::vec3> pointPositions;
|
||||
std::vector<glm::vec3> pointColors;
|
||||
int64_t nPoints;
|
||||
|
||||
std::ifstream pointFile(_pointsFilename, std::ios::in);
|
||||
|
||||
// Read header for OFF (Object File Format)
|
||||
std::string line;
|
||||
std::getline(pointFile, line);
|
||||
|
||||
// Read point count
|
||||
std::getline(pointFile, line);
|
||||
std::istringstream iss(line);
|
||||
iss >> nPoints;
|
||||
|
||||
// Prepare point reading
|
||||
_nPoints = static_cast<size_t>(nPoints);
|
||||
|
||||
// Read points
|
||||
float x, y, z, r, g, b, a;
|
||||
for (size_t i = 0;
|
||||
i < static_cast<size_t>(_nPoints * _enabledPointsRatio.maxValue()) + 1;
|
||||
++i)
|
||||
{
|
||||
std::getline(pointFile, line);
|
||||
std::istringstream issp(line);
|
||||
issp >> x >> y >> z >> r >> g >> b >> a;
|
||||
|
||||
// Convert kiloparsec to meters
|
||||
glm::vec3 position = glm::vec3(x, y, z);
|
||||
position *= (distanceconstants::Parsec * 100);
|
||||
|
||||
pointPositions.emplace_back(position);
|
||||
pointColors.emplace_back(r, g, b);
|
||||
}
|
||||
|
||||
Result res;
|
||||
res.success = true;
|
||||
res.positions = std::move(pointPositions);
|
||||
res.color = std::move(pointColors);
|
||||
return res;
|
||||
}
|
||||
|
||||
RenderableGalaxy::Result RenderableGalaxy::loadCachedFile(const std::string& file) {
|
||||
std::ifstream fileStream(file, std::ifstream::binary);
|
||||
if (!fileStream.good()) {
|
||||
LERROR(fmt::format("Error opening file '{}' for loading cache file", file));
|
||||
return { false, {}, {} };
|
||||
}
|
||||
|
||||
int8_t cacheVersion;
|
||||
fileStream.read(reinterpret_cast<char*>(&cacheVersion), sizeof(int8_t));
|
||||
if (cacheVersion != CurrentCacheVersion) {
|
||||
LINFO(fmt::format("Removing cache file '{}' as the version changed"));
|
||||
return { false, {}, {} };
|
||||
}
|
||||
|
||||
int64_t nPoints;
|
||||
fileStream.read(reinterpret_cast<char*>(&nPoints), sizeof(int64_t));
|
||||
_nPoints = static_cast<size_t>(nPoints);
|
||||
|
||||
float enabledPointsRatio;
|
||||
fileStream.read(reinterpret_cast<char*>(&enabledPointsRatio), sizeof(float));
|
||||
_enabledPointsRatio = enabledPointsRatio;
|
||||
|
||||
uint64_t nPositions;
|
||||
fileStream.read(reinterpret_cast<char*>(&nPositions), sizeof(uint64_t));
|
||||
std::vector<glm::vec3> positions;
|
||||
positions.resize(nPositions);
|
||||
fileStream.read(
|
||||
reinterpret_cast<char*>(positions.data()),
|
||||
nPositions * sizeof(glm::vec3)
|
||||
);
|
||||
|
||||
uint64_t nColors;
|
||||
fileStream.read(reinterpret_cast<char*>(&nColors), sizeof(uint64_t));
|
||||
std::vector<glm::vec3> colors;
|
||||
colors.resize(nColors);
|
||||
fileStream.read(
|
||||
reinterpret_cast<char*>(colors.data()),
|
||||
nColors * sizeof(glm::vec3)
|
||||
);
|
||||
|
||||
Result result;
|
||||
result.success = true;
|
||||
result.positions = std::move(positions);
|
||||
result.color = std::move(colors);
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
@@ -1,117 +0,0 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2020 *
|
||||
* *
|
||||
* 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_MODULE_GALAXY___RENDERABLEGALAXY___H__
|
||||
#define __OPENSPACE_MODULE_GALAXY___RENDERABLEGALAXY___H__
|
||||
|
||||
#include <openspace/rendering/renderable.h>
|
||||
|
||||
#include <openspace/properties/scalar/floatproperty.h>
|
||||
#include <openspace/properties/vector/vec3property.h>
|
||||
#include <openspace/properties/optionproperty.h>
|
||||
#include <ghoul/opengl/ghoul_gl.h>
|
||||
#include <ghoul/opengl/uniformcache.h>
|
||||
|
||||
namespace ghoul::opengl { class ProgramObject; }
|
||||
|
||||
namespace openspace {
|
||||
|
||||
namespace volume { template <typename T> class RawVolume; }
|
||||
|
||||
class GalaxyRaycaster;
|
||||
struct RenderData;
|
||||
|
||||
class RenderableGalaxy : public Renderable {
|
||||
public:
|
||||
explicit RenderableGalaxy(const ghoul::Dictionary& dictionary);
|
||||
virtual ~RenderableGalaxy() = default;
|
||||
|
||||
void initializeGL() override;
|
||||
void deinitializeGL() override;
|
||||
bool isReady() const override;
|
||||
void render(const RenderData& data, RendererTasks& tasks) override;
|
||||
void update(const UpdateData& data) override;
|
||||
|
||||
private:
|
||||
void renderPoints(const RenderData& data);
|
||||
void renderBillboards(const RenderData& data);
|
||||
float safeLength(const glm::vec3& vector) const;
|
||||
|
||||
struct Result {
|
||||
bool success;
|
||||
std::vector<glm::vec3> positions;
|
||||
std::vector<glm::vec3> color;
|
||||
};
|
||||
Result loadPointFile(const std::string& file);
|
||||
Result loadCachedFile(const std::string& file);
|
||||
|
||||
glm::vec3 _volumeSize = glm::vec3(0.f);
|
||||
glm::vec3 _pointScaling = glm::vec3(0.f);
|
||||
properties::BoolProperty _volumeRenderingEnabled;
|
||||
properties::BoolProperty _starRenderingEnabled;
|
||||
properties::FloatProperty _stepSize;
|
||||
properties::FloatProperty _absorptionMultiply;
|
||||
properties::FloatProperty _emissionMultiply;
|
||||
properties::OptionProperty _starRenderingMethod;
|
||||
properties::FloatProperty _enabledPointsRatio;
|
||||
properties::Vec3Property _translation;
|
||||
properties::Vec3Property _rotation;
|
||||
properties::FloatProperty _downScaleVolumeRendering;
|
||||
properties::FloatProperty _numberOfRayCastingSteps;
|
||||
|
||||
std::unique_ptr<ghoul::opengl::Texture> _pointSpreadFunctionTexture;
|
||||
std::unique_ptr<ghoul::filesystem::File> _pointSpreadFunctionFile;
|
||||
|
||||
std::string _volumeFilename;
|
||||
glm::ivec3 _volumeDimensions = glm::ivec3(0);
|
||||
std::string _pointsFilename;
|
||||
std::string _pointSpreadFunctionTexturePath;
|
||||
|
||||
std::unique_ptr<GalaxyRaycaster> _raycaster;
|
||||
std::unique_ptr<volume::RawVolume<glm::tvec4<GLubyte>>> _volume;
|
||||
std::unique_ptr<ghoul::opengl::Texture> _texture;
|
||||
glm::mat4 _pointTransform = glm::mat4(1.f);
|
||||
glm::vec3 _aspect = glm::vec3(0.f);
|
||||
float _opacityCoefficient = 0.f;
|
||||
|
||||
std::unique_ptr<ghoul::opengl::ProgramObject> _pointsProgram;
|
||||
std::unique_ptr<ghoul::opengl::ProgramObject> _billboardsProgram;
|
||||
UniformCache(
|
||||
modelMatrix, cameraViewProjectionMatrix, eyePosition,
|
||||
opacityCoefficient
|
||||
) _uniformCachePoints;
|
||||
UniformCache(
|
||||
modelMatrix, cameraViewProjectionMatrix,
|
||||
cameraUp, eyePosition, psfTexture
|
||||
) _uniformCacheBillboards;
|
||||
std::vector<float> _pointsData;
|
||||
size_t _nPoints = 0;
|
||||
GLuint _pointsVao = 0;
|
||||
GLuint _positionVbo = 0;
|
||||
GLuint _colorVbo = 0;
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
#endif // __OPENSPACE_MODULE_GALAXY___RENDERABLEGALAXY___H__
|
||||
@@ -0,0 +1,102 @@
|
||||
openspace.gaia.documentation = {
|
||||
{
|
||||
Name = "addClippingBox",
|
||||
Arguments = "string, vec3, vec3",
|
||||
Documentation = "Creates a clipping box for the Gaia renderable in the first argument"
|
||||
},
|
||||
{
|
||||
Name = "removeClippingBox",
|
||||
Arguments = "",
|
||||
Documentation = ""
|
||||
},
|
||||
{
|
||||
Name = "addClippingSphere",
|
||||
Arguments = "string, float",
|
||||
Documentation = "Creates a clipping sphere for the Gaia renderable in the first argument"
|
||||
},
|
||||
{
|
||||
Name = "removeClippingBox",
|
||||
Arguments = "",
|
||||
Documentation = ""
|
||||
}
|
||||
}
|
||||
|
||||
openspace.gaia.addClippingBox = function (name, size, position)
|
||||
local grid_identifier = "Filtering_Box"
|
||||
local kilo_parsec_in_meter = 30856775814913700000
|
||||
|
||||
if openspace.hasSceneGraphNode(grid_identifier) then
|
||||
openspace.removeSceneGraphNode(grid_identifier)
|
||||
end
|
||||
|
||||
local grid = {
|
||||
Identifier = grid_identifier,
|
||||
Transform = {
|
||||
Translation = {
|
||||
Type = "StaticTranslation",
|
||||
Position = { position[1] * kilo_parsec_in_meter, position[2] * kilo_parsec_in_meter, position[3] * kilo_parsec_in_meter }
|
||||
}
|
||||
},
|
||||
Renderable = {
|
||||
Type = "RenderableBoxGrid",
|
||||
GridColor = { 0.6, 0.5, 0.7, 1.0 },
|
||||
LineWidth = 2.0,
|
||||
Size = { size[1] * kilo_parsec_in_meter, size[2] * kilo_parsec_in_meter, size[3] * kilo_parsec_in_meter}
|
||||
},
|
||||
GUI = {
|
||||
Name = "Filtering Grid",
|
||||
Path = "/Other/Grids"
|
||||
}
|
||||
}
|
||||
|
||||
openspace.addSceneGraphNode(grid)
|
||||
|
||||
openspace.setPropertyValue('Scene.' .. name .. '.renderable.FilterPosX', { (position[1] - size[1] / 2) * kilo_parsec_in_meter, (position[1] + size[1] / 2) * kilo_parsec_in_meter })
|
||||
openspace.setPropertyValue('Scene.' .. name .. '.renderable.FilterPosY', { (position[2] - size[2] / 2) * kilo_parsec_in_meter, (position[2] + size[2] / 2) * kilo_parsec_in_meter })
|
||||
openspace.setPropertyValue('Scene.' .. name .. '.renderable.FilterPosZ', { (position[3] - size[3] / 2) * kilo_parsec_in_meter, (position[3] + size[3] / 2) * kilo_parsec_in_meter })
|
||||
end
|
||||
|
||||
openspace.gaia.removeClippingBox = function()
|
||||
local grid_identifier = "Filtering_Box"
|
||||
|
||||
if openspace.hasSceneGraphNode(grid_identifier) then
|
||||
openspace.removeSceneGraphNode(grid_identifier)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
openspace.gaia.addClippingSphere = function (name, radius)
|
||||
local grid_identifier = "Filtering_Sphere"
|
||||
local kilo_parsec_in_meter = 30856775814913700000
|
||||
|
||||
|
||||
if openspace.hasSceneGraphNode(grid_identifier) then
|
||||
openspace.removeSceneGraphNode(grid_identifier)
|
||||
end
|
||||
|
||||
local grid = {
|
||||
Identifier = grid_identifier,
|
||||
Renderable = {
|
||||
Type = "RenderableSphericalGrid",
|
||||
GridColor = { 0.6, 0.5, 0.7, 1.0 },
|
||||
LineWidth = 1.0,
|
||||
Radius = radius * kilo_parsec_in_meter
|
||||
},
|
||||
GUI = {
|
||||
Name = "Filtering Sphere",
|
||||
Path = "/Other/Grids"
|
||||
}
|
||||
}
|
||||
|
||||
openspace.addSceneGraphNode(grid)
|
||||
|
||||
openspace.setPropertyValue('Scene.' .. name .. '.renderable.FilterDist', radius * kilo_parsec_in_meter)
|
||||
end
|
||||
|
||||
openspace.gaia.removeClippingSphere = function()
|
||||
local grid_identifier = "Filtering_Sphere"
|
||||
|
||||
if openspace.hasSceneGraphNode(grid_identifier) then
|
||||
openspace.removeSceneGraphNode(grid_identifier)
|
||||
end
|
||||
end
|
||||
@@ -1,101 +0,0 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2020 *
|
||||
* *
|
||||
* 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__
|
||||
|
||||
#include "floatoperations.glsl"
|
||||
#include "PowerScaling/powerScalingMath.hglsl"
|
||||
|
||||
uniform dvec3 eyePosition;
|
||||
uniform dvec3 cameraUp;
|
||||
uniform dmat4 cameraViewProjectionMatrix;
|
||||
uniform dmat4 modelMatrix;
|
||||
|
||||
layout(points) in;
|
||||
layout(triangle_strip, max_vertices = 4) out;
|
||||
|
||||
in vec4 vs_gPosition[];
|
||||
in vec3 vs_color[];
|
||||
|
||||
out vec4 vs_position;
|
||||
out vec2 psfCoords;
|
||||
flat out vec3 ge_color;
|
||||
flat out float ge_screenSpaceDepth;
|
||||
|
||||
const double PARSEC = 3.08567756E16;
|
||||
|
||||
void main() {
|
||||
vs_position = gl_in[0].gl_Position; // in object space
|
||||
ge_color = vs_color[0];
|
||||
|
||||
double scaleMultiply = 8.0;
|
||||
|
||||
dvec4 dpos = dvec4(vs_position);
|
||||
dpos.xyz *= scaleMultiply;
|
||||
dpos = modelMatrix * dpos;
|
||||
dpos /= PARSEC;
|
||||
//It lies about 8 kpc from the center on what is known as the Orion Arm of the Milky Way
|
||||
dpos.x += 8000;
|
||||
|
||||
scaleMultiply *= 4.0;
|
||||
dvec3 scaledRight = dvec3(0.0);
|
||||
dvec3 scaledUp = dvec3(0.0);
|
||||
vec4 bottomLeftVertex, bottomRightVertex, topLeftVertex, topRightVertex;
|
||||
|
||||
dvec3 normal = normalize(eyePosition - dpos.xyz);
|
||||
dvec3 newRight = normalize(cross(cameraUp, normal));
|
||||
dvec3 newUp = cross(normal, newRight);
|
||||
scaledRight = scaleMultiply * newRight;
|
||||
scaledUp = scaleMultiply * newUp;
|
||||
|
||||
bottomLeftVertex = z_normalization(vec4(cameraViewProjectionMatrix *
|
||||
dvec4(dpos.xyz - scaledRight - scaledUp, dpos.w)));
|
||||
|
||||
//dvec4 dposCamera = cameraViewProjectionMatrix * dpos;
|
||||
//ge_screenSpaceDepth = float(length(eyePosition - dposCamera.xyz)/PARSEC);
|
||||
ge_screenSpaceDepth = bottomLeftVertex.w;
|
||||
|
||||
topRightVertex = z_normalization(vec4(cameraViewProjectionMatrix *
|
||||
dvec4(dpos.xyz + scaledUp + scaledRight, dpos.w)));
|
||||
|
||||
bottomRightVertex = z_normalization(vec4(cameraViewProjectionMatrix *
|
||||
dvec4(dpos.xyz + scaledRight - scaledUp, dpos.w)));
|
||||
topLeftVertex = z_normalization(vec4(cameraViewProjectionMatrix *
|
||||
dvec4(dpos.xyz + scaledUp - scaledRight, dpos.w)));
|
||||
|
||||
// Build primitive
|
||||
gl_Position = topLeftVertex;
|
||||
psfCoords = vec2(-1.0, 1.0);
|
||||
EmitVertex();
|
||||
gl_Position = bottomLeftVertex;
|
||||
psfCoords = vec2(-1.0, -1.0);
|
||||
EmitVertex();
|
||||
gl_Position = topRightVertex;
|
||||
psfCoords = vec2(1.0, 1.0);
|
||||
EmitVertex();
|
||||
gl_Position = bottomRightVertex;
|
||||
psfCoords = vec2(1.0, -1.0);
|
||||
EmitVertex();
|
||||
EndPrimitive();
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2020 *
|
||||
* *
|
||||
* 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__
|
||||
|
||||
#include "floatoperations.glsl"
|
||||
|
||||
layout (location = 0) out vec4 outColor;
|
||||
|
||||
// Keep in sync with gaiaoptions.h:RenderOption enum
|
||||
const int RENDEROPTION_STATIC = 0;
|
||||
const int RENDEROPTION_COLOR = 1;
|
||||
const int RENDEROPTION_MOTION = 2;
|
||||
const float ONE_PARSEC = 3.08567758e16; // 1 Parsec
|
||||
const float FLT_MAX = 3.402823466e38; // Max float constant in GLSL
|
||||
const float LUM_LOWER_CAP = 0.01;
|
||||
|
||||
in vec2 ge_brightness;
|
||||
in vec4 ge_gPosition;
|
||||
in vec2 texCoord;
|
||||
in float ge_starDistFromSun;
|
||||
in float ge_cameraDistFromSun;
|
||||
in float ge_observedDist;
|
||||
|
||||
uniform sampler2D psfTexture;
|
||||
uniform sampler1D colorTexture;
|
||||
uniform float luminosityMultiplier;
|
||||
uniform float sharpness;
|
||||
uniform int renderOption;
|
||||
|
||||
vec3 color2rgb(float color) {
|
||||
// BV is [-0.4, 2.0]
|
||||
float st = (color + 0.4) / (2.0 + 0.4);
|
||||
|
||||
// Bp-Rp[-2.0, 6.5], Bp-G[-2.1, 5.0], G-Rp[-1.0, 3.0]
|
||||
//float st = (color + 1.0) / (5.0 + 1.0);
|
||||
|
||||
return texture(colorTexture, st).rgb;
|
||||
}
|
||||
|
||||
void main() {
|
||||
|
||||
// Assume all stars has equal luminosity as the Sun when no magnitude is loaded.
|
||||
float luminosity = 0.05;
|
||||
vec3 color = vec3(luminosity);
|
||||
float ratioMultiplier = 0.05;
|
||||
|
||||
vec4 textureColor = texture(psfTexture, texCoord);
|
||||
textureColor.a = pow(textureColor.a, sharpness);
|
||||
if (textureColor.a < 0.001) {
|
||||
discard;
|
||||
}
|
||||
|
||||
// Calculate the color and luminosity if we have the magnitude and B-V color.
|
||||
if ( renderOption != RENDEROPTION_STATIC ) {
|
||||
color = color2rgb(ge_brightness.y);
|
||||
ratioMultiplier = 0.5;
|
||||
|
||||
// Absolute magnitude is brightness a star would have at 10 pc away.
|
||||
float absoluteMagnitude = ge_brightness.x;
|
||||
|
||||
// From formula: MagSun - MagStar = 2.5*log(LumStar / LumSun), it gives that:
|
||||
// LumStar = 10^(1.89 - 0.4*Magstar) , if LumSun = 1 and MagSun = 4.72
|
||||
luminosity = pow(10.0, 1.89 - 0.4 * absoluteMagnitude);
|
||||
|
||||
// If luminosity is really really small then set it to a static low number.
|
||||
if (luminosity < LUM_LOWER_CAP) {
|
||||
luminosity = LUM_LOWER_CAP;
|
||||
}
|
||||
}
|
||||
|
||||
// Luminosity decrease by {squared} distance [measured in Pc].
|
||||
float observedDistance = ge_observedDist / ONE_PARSEC;
|
||||
luminosity /= pow(observedDistance, 2.0);
|
||||
|
||||
// Multiply our color with the luminosity as well as a user-controlled property.
|
||||
color *= luminosity * pow(luminosityMultiplier, 3.0);
|
||||
|
||||
// Decrease contributing brightness for stars in central cluster.
|
||||
if ( ge_cameraDistFromSun > ge_starDistFromSun ) {
|
||||
float ratio = ge_starDistFromSun / ge_cameraDistFromSun;
|
||||
//color *= ratio * ratioMultiplier;
|
||||
}
|
||||
|
||||
// Use truncating tonemapping here so we don't overexposure individual stars.
|
||||
//color = 1.0 - 1.0 * exp(-5.0 * color.rgb);
|
||||
float maxVal = max(max(color.r, color.g), color.b);
|
||||
if (maxVal > 1.0) {
|
||||
color /= maxVal;
|
||||
}
|
||||
|
||||
outColor = vec4(color, textureColor.a);
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2020 *
|
||||
* *
|
||||
* 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__
|
||||
|
||||
#include "floatoperations.glsl"
|
||||
|
||||
// Keep in sync with gaiaoptions.h:RenderOption enum
|
||||
const int RENDEROPTION_STATIC = 0;
|
||||
const int RENDEROPTION_COLOR = 1;
|
||||
const int RENDEROPTION_MOTION = 2;
|
||||
const float EPS = 1e-5;
|
||||
|
||||
layout(points) in;
|
||||
in vec2 vs_brightness[];
|
||||
in vec4 vs_gPosition[];
|
||||
in float vs_starDistFromSun[];
|
||||
in float vs_cameraDistFromSun[];
|
||||
|
||||
layout(triangle_strip, max_vertices = 4) out;
|
||||
out vec2 ge_brightness;
|
||||
out vec4 ge_gPosition;
|
||||
out vec2 texCoord;
|
||||
out float ge_starDistFromSun;
|
||||
out float ge_cameraDistFromSun;
|
||||
out float ge_observedDist;
|
||||
|
||||
uniform dmat4 view;
|
||||
uniform dmat4 projection;
|
||||
|
||||
uniform dvec3 cameraPos;
|
||||
uniform dvec3 cameraLookUp;
|
||||
uniform float viewScaling;
|
||||
uniform float cutOffThreshold;
|
||||
uniform float closeUpBoostDist;
|
||||
uniform float billboardSize;
|
||||
uniform int renderOption;
|
||||
uniform float magnitudeBoost;
|
||||
|
||||
const vec2 corners[4] = vec2[4](
|
||||
vec2(0.0, 1.0),
|
||||
vec2(0.0, 0.0),
|
||||
vec2(1.0, 1.0),
|
||||
vec2(1.0, 0.0)
|
||||
);
|
||||
|
||||
|
||||
void main() {
|
||||
|
||||
ge_brightness = vs_brightness[0];
|
||||
ge_starDistFromSun = vs_starDistFromSun[0];
|
||||
ge_cameraDistFromSun = vs_cameraDistFromSun[0];
|
||||
|
||||
vec4 viewPosition = vec4(view * vs_gPosition[0]);
|
||||
|
||||
// Make closer stars look a bit bigger.
|
||||
ge_observedDist = safeLength(viewPosition / viewScaling);
|
||||
float closeUpBoost = closeUpBoostDist / ge_observedDist;
|
||||
float initStarSize = billboardSize;
|
||||
|
||||
// Use magnitude for size boost as well.
|
||||
if ( renderOption != RENDEROPTION_STATIC ) {
|
||||
// DR1 magnitudes are [4, 20], but could be [-15, 20] according to this chart:
|
||||
// https://qph.fs.quoracdn.net/main-qimg-317a18e3b228efc7d7f67a1632a55961
|
||||
// Negative magnitude => Giants
|
||||
// Big positive magnitude => Dwarfs
|
||||
float absoluteMagnitude = vs_brightness[0].x;
|
||||
float normalizedMagnitude = (absoluteMagnitude - 20) / -1; // (-15 - 20);
|
||||
|
||||
// TODO: A linear scale is prabably not the best!
|
||||
initStarSize += normalizedMagnitude * (magnitudeBoost / 50);
|
||||
}
|
||||
|
||||
vec4 position = gl_in[0].gl_Position;
|
||||
vec2 starSize = vec2(initStarSize + closeUpBoost) * position.w / 1000.0;
|
||||
|
||||
float distThreshold = cutOffThreshold - log(ge_observedDist) / log(4.0);
|
||||
|
||||
// Discard geometry if star has no position (but wasn't a nullArray).
|
||||
// Or if observed distance is above threshold set by cutOffThreshold.
|
||||
// By discarding in gs instead of fs we save computations for when nothing is visible.
|
||||
if (length(position) < EPS || distThreshold <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
vec4 centerWorldPos = vs_gPosition[0];
|
||||
|
||||
dvec3 cameraNormal = normalize(cameraPos - dvec3(centerWorldPos.xyz));
|
||||
dvec3 newRight = normalize(cross(cameraLookUp, cameraNormal));
|
||||
dvec3 newUp = cross(cameraNormal, newRight);
|
||||
vec4 wCameraRight = vec4(newRight, 0.0);
|
||||
vec4 wCameraUp = vec4(newUp, 0.0);
|
||||
|
||||
float multiplier = float(length(cameraPos));
|
||||
starSize *= float(multiplier/1E1);
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
// Always turn the billboard towards the camera (needed for warped screen).
|
||||
vec4 cornerPoint = centerWorldPos
|
||||
+ wCameraRight * starSize.x * (corners[i].x - 0.5)
|
||||
+ wCameraUp * starSize.y * (corners[i].y - 0.5);
|
||||
gl_Position = vec4(projection * view * cornerPoint);
|
||||
gl_Position.z = 0.0;
|
||||
texCoord = corners[i];
|
||||
ge_gPosition = viewPosition;
|
||||
|
||||
EmitVertex();
|
||||
}
|
||||
|
||||
EndPrimitive();
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2020 *
|
||||
* *
|
||||
* 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 "fragment.glsl"
|
||||
#include "floatoperations.glsl"
|
||||
|
||||
// Keep in sync with gaiaoptions.h:RenderOption enum
|
||||
const int RENDEROPTION_STATIC = 0;
|
||||
const int RENDEROPTION_COLOR = 1;
|
||||
const int RENDEROPTION_MOTION = 2;
|
||||
const float ONE_PARSEC = 3.08567758e16; // 1 Parsec
|
||||
const float DEFAULT_DEPTH = 3.08567758e19; // 1000 Pc
|
||||
const float LUM_LOWER_CAP = 0.01;
|
||||
|
||||
in vec2 ge_brightness;
|
||||
in vec4 ge_gPosition;
|
||||
in vec2 texCoord;
|
||||
in float ge_starDistFromSun;
|
||||
in float ge_cameraDistFromSun;
|
||||
in float ge_observedDist;
|
||||
|
||||
uniform sampler2D psfTexture;
|
||||
uniform sampler1D colorTexture;
|
||||
uniform float luminosityMultiplier;
|
||||
uniform float sharpness;
|
||||
uniform int renderOption;
|
||||
|
||||
vec3 color2rgb(float color) {
|
||||
// BV is [-0.4, 2.0]
|
||||
float st = (color + 0.4) / (2.0 + 0.4);
|
||||
|
||||
// Bp-Rp[-2.0, 6.5], Bp-G[-2.1, 5.0], G-Rp[-1.0, 3.0]
|
||||
//float st = (color + 1.0) / (5.0 + 1.0);
|
||||
|
||||
return texture(colorTexture, st).rgb;
|
||||
}
|
||||
|
||||
Fragment getFragment() {
|
||||
|
||||
// Assume all stars has equal luminosity as the Sun when no magnitude is loaded.
|
||||
float luminosity = 1.0;
|
||||
vec3 color = vec3(luminosity);
|
||||
float ratioMultiplier = 0.03;
|
||||
|
||||
vec4 textureColor = texture(psfTexture, texCoord);
|
||||
textureColor.a = pow(textureColor.a, sharpness);
|
||||
if (textureColor.a < 0.001) {
|
||||
discard;
|
||||
}
|
||||
|
||||
// Calculate the color and luminosity if we have the magnitude and B-V color.
|
||||
if ( renderOption != RENDEROPTION_STATIC ) {
|
||||
color = color2rgb(ge_brightness.y);
|
||||
ratioMultiplier = 0.5;
|
||||
|
||||
// Absolute magnitude is brightness a star would have at 10 pc away.
|
||||
float absoluteMagnitude = ge_brightness.x;
|
||||
|
||||
// From formula: MagSun - MagStar = 2.5*log(LumStar / LumSun), it gives that:
|
||||
// LumStar = 10^(1.89 - 0.4*Magstar) , if LumSun = 1 and MagSun = 4.72
|
||||
luminosity = pow(10.0, 1.89 - 0.4 * absoluteMagnitude);
|
||||
|
||||
// If luminosity is really really small then set it to a static low number.
|
||||
if (luminosity < LUM_LOWER_CAP) {
|
||||
luminosity = LUM_LOWER_CAP;
|
||||
}
|
||||
}
|
||||
|
||||
// Luminosity decrease by {squared} distance [measured in Pc].
|
||||
float observedDistance = ge_observedDist / ONE_PARSEC;
|
||||
luminosity /= pow(observedDistance, 2.0);
|
||||
|
||||
// Multiply our color with the luminosity as well as a user-controlled property.
|
||||
color *= luminosity * pow(luminosityMultiplier, 3.0);
|
||||
|
||||
// Decrease contributing brightness for stars in central cluster.
|
||||
if ( ge_cameraDistFromSun > ge_starDistFromSun ) {
|
||||
float ratio = ge_starDistFromSun / ge_cameraDistFromSun;
|
||||
//color *= ratio * ratioMultiplier;
|
||||
}
|
||||
|
||||
// Use truncating tonemapping here so we don't overexposure individual stars.
|
||||
//color = 1.0 - 1.0 * exp(-5.0 * color.rgb);
|
||||
float maxVal = max(max(color.r, color.g), color.b);
|
||||
if (maxVal > 1.0) {
|
||||
color /= maxVal;
|
||||
}
|
||||
|
||||
if (length(color) < 0.01) {
|
||||
discard;
|
||||
}
|
||||
|
||||
Fragment frag;
|
||||
frag.color = vec4(color, textureColor.a);;
|
||||
// Place stars at back to begin with.
|
||||
frag.depth = DEFAULT_DEPTH;
|
||||
frag.gNormal = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
frag.blend = BLEND_MODE_NORMAL;
|
||||
|
||||
return frag;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2020 *
|
||||
* *
|
||||
* 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__
|
||||
|
||||
#include "floatoperations.glsl"
|
||||
|
||||
layout (location = 0) out vec4 outColor;
|
||||
|
||||
// Keep in sync with gaiaoptions.h:RenderOption enum
|
||||
const int RENDEROPTION_STATIC = 0;
|
||||
const int RENDEROPTION_COLOR = 1;
|
||||
const int RENDEROPTION_MOTION = 2;
|
||||
const float ONE_PARSEC = 3.08567758e16; // 1 Parsec
|
||||
const float LUM_LOWER_CAP = 0.01;
|
||||
|
||||
in vec2 ge_brightness;
|
||||
in vec4 ge_gPosition;
|
||||
in float ge_starDistFromSun;
|
||||
in float ge_cameraDistFromSun;
|
||||
in float ge_observedDist;
|
||||
|
||||
uniform sampler1D colorTexture;
|
||||
uniform float luminosityMultiplier;
|
||||
uniform int renderOption;
|
||||
uniform float viewScaling;
|
||||
|
||||
vec3 color2rgb(float color) {
|
||||
// BV is [-0.4, 2.0]
|
||||
float st = (color + 0.4) / (2.0 + 0.4);
|
||||
|
||||
// Bp-Rp[-2.0, 6.5], Bp-G[-2.1, 5.0], G-Rp[-1.0, 3.0]
|
||||
//float st = (color + 1.0) / (5.0 + 1.0);
|
||||
|
||||
return texture(colorTexture, st).rgb;
|
||||
}
|
||||
|
||||
void main() {
|
||||
|
||||
// Assume all stars has equal luminosity as the Sun when no magnitude is loaded.
|
||||
float luminosity = 0.05;
|
||||
vec3 color = vec3(luminosity);
|
||||
float ratioMultiplier = 1.0;
|
||||
|
||||
// Calculate the color and luminosity if we have the magnitude and B-V color.
|
||||
if ( renderOption != RENDEROPTION_STATIC ) {
|
||||
color = color2rgb(ge_brightness.y);
|
||||
ratioMultiplier = 0.01;
|
||||
|
||||
// Absolute magnitude is brightness a star would have at 10 pc away.
|
||||
float absoluteMagnitude = ge_brightness.x;
|
||||
|
||||
// From formula: MagSun - MagStar = 2.5*log(LumStar / LumSun), it gives that:
|
||||
// LumStar = 10^(1.89 - 0.4*Magstar) , if LumSun = 1 and MagSun = 4.72
|
||||
luminosity = pow(10.0, 1.89 - 0.4 * absoluteMagnitude);
|
||||
|
||||
// If luminosity is really really small then set it to a static low number.
|
||||
if (luminosity < LUM_LOWER_CAP) {
|
||||
luminosity = LUM_LOWER_CAP;
|
||||
}
|
||||
}
|
||||
|
||||
// Luminosity decrease by {squared} distance [measured in Pc].
|
||||
float observedDistance = ge_observedDist / ONE_PARSEC;
|
||||
luminosity /= pow(observedDistance, 2.0);
|
||||
|
||||
// Multiply our color with the luminosity as well as a user-controlled property.
|
||||
color *= luminosity * pow(luminosityMultiplier, 3.0);
|
||||
|
||||
// Decrease contributing brightness for stars in central cluster.
|
||||
if ( ge_cameraDistFromSun > ge_starDistFromSun ) {
|
||||
float ratio = ge_starDistFromSun / ge_cameraDistFromSun;
|
||||
//color *= ratio * ratioMultiplier;
|
||||
}
|
||||
|
||||
outColor = vec4(color, 1.0f);
|
||||
}
|
||||
+40
-22
@@ -24,35 +24,53 @@
|
||||
|
||||
#version __CONTEXT__
|
||||
|
||||
#include "PowerScaling/powerScaling_vs.hglsl"
|
||||
#include "floatoperations.glsl"
|
||||
|
||||
layout(location = 0) in vec3 in_position;
|
||||
layout(location = 1) in vec3 in_color;
|
||||
const float EPS = 1e-5;
|
||||
|
||||
out vec4 vs_position;
|
||||
out vec3 vs_color;
|
||||
out float vs_screenSpaceDepth;
|
||||
out float vs_starBrightness;
|
||||
layout(points) in;
|
||||
in vec2 vs_brightness[];
|
||||
in vec4 vs_gPosition[];
|
||||
in float vs_starDistFromSun[];
|
||||
in float vs_cameraDistFromSun[];
|
||||
|
||||
uniform dmat4 cameraViewProjectionMatrix;
|
||||
uniform dmat4 modelMatrix;
|
||||
uniform dvec3 eyePosition;
|
||||
layout(points, max_vertices = 1) out;
|
||||
out vec2 ge_brightness;
|
||||
out vec4 ge_gPosition;
|
||||
out float ge_starDistFromSun;
|
||||
out float ge_cameraDistFromSun;
|
||||
out float ge_observedDist;
|
||||
|
||||
const double PARSEC = 3.08567756E16;
|
||||
uniform dmat4 view;
|
||||
uniform float viewScaling;
|
||||
uniform float cutOffThreshold;
|
||||
|
||||
void main() {
|
||||
vs_position = vec4(in_position, 1.0);
|
||||
dvec4 dpos = dvec4(vs_position);
|
||||
|
||||
double distanceToStar = length((dpos.xyz - eyePosition));
|
||||
vs_starBrightness = clamp(float(8000*PARSEC/distanceToStar), 0.0, 1.0);
|
||||
ge_brightness = vs_brightness[0];
|
||||
ge_starDistFromSun = vs_starDistFromSun[0];
|
||||
ge_cameraDistFromSun = vs_cameraDistFromSun[0];
|
||||
|
||||
dpos.xyz *= 8.0;
|
||||
dpos = modelMatrix * dpos;
|
||||
dpos /= PARSEC;
|
||||
vec4 viewPosition = vec4(view * vs_gPosition[0]);
|
||||
|
||||
vec4 positionScreenSpace = z_normalization(vec4(cameraViewProjectionMatrix * dpos));
|
||||
vs_color = in_color;
|
||||
vs_screenSpaceDepth = positionScreenSpace.w;
|
||||
gl_Position = positionScreenSpace;
|
||||
ge_observedDist = safeLength(viewPosition / viewScaling);
|
||||
float distThreshold = cutOffThreshold - log(ge_observedDist) / log(4.0);
|
||||
|
||||
vec4 position = gl_in[0].gl_Position;
|
||||
|
||||
// Discard geometry if star has no position (but wasn't a nullArray).
|
||||
// Or if observed distance is above threshold set by cutOffThreshold.
|
||||
// By discarding in gs instead of fs we save computations for when nothing is visible.
|
||||
if (length(position) < EPS || distThreshold <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
//gl_PointSize = 1.0;
|
||||
gl_Position = position;
|
||||
gl_Position.z = 0.0;
|
||||
ge_gPosition = viewPosition;
|
||||
|
||||
EmitVertex();
|
||||
|
||||
EndPrimitive();
|
||||
}
|
||||
@@ -0,0 +1,187 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2020 *
|
||||
* *
|
||||
* 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__
|
||||
|
||||
#include "floatoperations.glsl"
|
||||
|
||||
// Keep in sync with gaiaoptions.h:RenderOption enum
|
||||
const int RENDEROPTION_STATIC = 0;
|
||||
const int RENDEROPTION_COLOR = 1;
|
||||
const int RENDEROPTION_MOTION = 2;
|
||||
const float EPS = 1e-5;
|
||||
const float Parsec = 3.0856776e16;
|
||||
|
||||
layout (std430) buffer ssbo_idx_data {
|
||||
int starsPerChunk[];
|
||||
};
|
||||
|
||||
layout (std430) buffer ssbo_comb_data {
|
||||
float allData[];
|
||||
};
|
||||
|
||||
in int gl_VertexID;
|
||||
|
||||
out vec2 vs_brightness;
|
||||
out vec4 vs_gPosition;
|
||||
out float vs_starDistFromSun;
|
||||
out float vs_cameraDistFromSun;
|
||||
|
||||
uniform dmat4 model;
|
||||
uniform dmat4 view;
|
||||
uniform dmat4 projection;
|
||||
uniform float time;
|
||||
uniform int renderOption;
|
||||
|
||||
uniform int maxStarsPerNode;
|
||||
uniform int valuesPerStar;
|
||||
uniform int nChunksToRender;
|
||||
|
||||
uniform vec2 posXThreshold;
|
||||
uniform vec2 posYThreshold;
|
||||
uniform vec2 posZThreshold;
|
||||
uniform vec2 gMagThreshold;
|
||||
uniform vec2 bpRpThreshold;
|
||||
uniform vec2 distThreshold;
|
||||
|
||||
// Use binary search to find the chunk containing our star ID.
|
||||
int findChunkId(int left, int right, int id) {
|
||||
|
||||
while ( left <= right ) {
|
||||
int middle = (left + right) / 2;
|
||||
int firstStarInChunk = starsPerChunk[middle];
|
||||
if (left == right || (firstStarInChunk <= id && id < starsPerChunk[middle+1])) {
|
||||
return middle;
|
||||
}
|
||||
else if (id < firstStarInChunk) {
|
||||
// Go smaller
|
||||
right = middle - 1;
|
||||
}
|
||||
else {
|
||||
// Go bigger
|
||||
left = middle + 1;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void main() {
|
||||
// Fetch our data.
|
||||
int chunkId = findChunkId(0, nChunksToRender - 1, gl_VertexID);
|
||||
// Fail safe - this should never happen!
|
||||
if (chunkId == -1) {
|
||||
vs_gPosition = vec4(0.0);
|
||||
gl_Position = vec4(0.0);
|
||||
return;
|
||||
}
|
||||
int placeInChunk = gl_VertexID - starsPerChunk[chunkId];
|
||||
int firstStarInChunk = valuesPerStar * maxStarsPerNode * chunkId; // Chunk offset
|
||||
int nStarsInChunk = starsPerChunk[chunkId + 1] - starsPerChunk[chunkId]; // Stars in current chunk.
|
||||
// Remove possible duplicates.
|
||||
if (nStarsInChunk <= 0) {
|
||||
vs_gPosition = vec4(0.0);
|
||||
gl_Position = vec4(0.0);
|
||||
return;
|
||||
}
|
||||
|
||||
int startOfPos = firstStarInChunk + placeInChunk * 3;
|
||||
vec3 in_position = vec3(allData[startOfPos], allData[startOfPos + 1], allData[startOfPos + 2]);
|
||||
vec2 in_brightness = vec2(0.0);
|
||||
vec3 in_velocity = vec3(0.0);
|
||||
|
||||
// Check if we should filter this star by position.
|
||||
if ( (abs(posXThreshold.x) > EPS && in_position.x < posXThreshold.x) ||
|
||||
(abs(posXThreshold.y) > EPS && in_position.x > posXThreshold.y) ||
|
||||
(abs(posYThreshold.x) > EPS && in_position.y < posYThreshold.x) ||
|
||||
(abs(posYThreshold.y) > EPS && in_position.y > posYThreshold.y) ||
|
||||
(abs(posZThreshold.x) > EPS && in_position.z < posZThreshold.x) ||
|
||||
(abs(posZThreshold.y) > EPS && in_position.z > posZThreshold.y) ||
|
||||
(abs(distThreshold.x - distThreshold.y) < EPS
|
||||
&& abs(length(in_position) - distThreshold.y) < EPS) ) {
|
||||
// Discard star in geometry shader.
|
||||
vs_gPosition = vec4(0.0);
|
||||
gl_Position = vec4(0.0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if ( renderOption != RENDEROPTION_STATIC ) {
|
||||
int startOfCol = firstStarInChunk + nStarsInChunk * 3 + placeInChunk * 2;
|
||||
in_brightness = vec2(allData[startOfCol], allData[startOfCol + 1]);
|
||||
|
||||
// Check if we should filter this star by magnitude or color.
|
||||
if ( (abs(gMagThreshold.x - gMagThreshold.y) < EPS && abs(gMagThreshold.x - in_brightness.x) < EPS) ||
|
||||
(abs(gMagThreshold.x - 20.0f) > EPS && in_brightness.x < gMagThreshold.x) ||
|
||||
(abs(gMagThreshold.y - 20.0f) > EPS && in_brightness.x > gMagThreshold.y) ||
|
||||
(abs(bpRpThreshold.x - bpRpThreshold.y) < EPS && abs(bpRpThreshold.x - in_brightness.y) < EPS) ||
|
||||
(abs(bpRpThreshold.x) > EPS && in_brightness.y < bpRpThreshold.x) ||
|
||||
(abs(bpRpThreshold.y) > EPS && in_brightness.y > bpRpThreshold.y) ) {
|
||||
// Discard star in geometry shader.
|
||||
vs_gPosition = vec4(0.0);
|
||||
gl_Position = vec4(0.0);
|
||||
return;
|
||||
}
|
||||
|
||||
if ( renderOption == RENDEROPTION_MOTION ) {
|
||||
int startOfVel = firstStarInChunk + nStarsInChunk * 5 + placeInChunk * 3;
|
||||
in_velocity = vec3(allData[startOfVel], allData[startOfVel + 1], allData[startOfVel + 2]);
|
||||
}
|
||||
}
|
||||
vs_brightness = in_brightness;
|
||||
|
||||
// Convert kiloParsec to meter.
|
||||
vec4 objectPosition = vec4(in_position * 1000 * Parsec, 1.0);
|
||||
|
||||
// Add velocity [m/s] if we've read any.
|
||||
objectPosition.xyz += time * in_velocity;
|
||||
|
||||
// Thres moving stars by their new position.
|
||||
float distPosition = length(objectPosition.xyz / (1000.0 * Parsec) );
|
||||
if ( (abs(distThreshold.x - distThreshold.y) > EPS &&
|
||||
((abs(distThreshold.x) > EPS && distPosition < distThreshold.x) ||
|
||||
(abs(distThreshold.y) > EPS && distPosition > distThreshold.y))) ) {
|
||||
// Discard star in geometry shader.
|
||||
vs_gPosition = vec4(0.0);
|
||||
gl_Position = vec4(0.0);
|
||||
return;
|
||||
}
|
||||
|
||||
// Apply camera transforms.
|
||||
dvec4 viewPosition = view * model * objectPosition;
|
||||
vec4 sunPosition = vec4(view * model * dvec4(0.0f, 0.0f, 0.0f, 1.0f));
|
||||
|
||||
vs_starDistFromSun = safeLength(objectPosition);
|
||||
vs_cameraDistFromSun = safeLength(sunPosition);
|
||||
|
||||
// Remove stars without position, happens when VBO chunk is stuffed with zeros.
|
||||
// Has to be done in Geometry shader because Vertices cannot be discarded here.
|
||||
if ( length(in_position) > EPS ){
|
||||
vs_gPosition = vec4(model * objectPosition);
|
||||
gl_Position = vec4(projection * viewPosition);
|
||||
}
|
||||
else {
|
||||
vs_gPosition = vec4(0.0);
|
||||
gl_Position = vec4(0.0);
|
||||
}
|
||||
}
|
||||
+19
-16
@@ -23,28 +23,31 @@
|
||||
****************************************************************************************/
|
||||
|
||||
#include "fragment.glsl"
|
||||
#include "floatoperations.glsl"
|
||||
|
||||
uniform sampler2D psfTexture;
|
||||
in vec2 uv;
|
||||
|
||||
uniform sampler2D renderedTexture;
|
||||
|
||||
const float DEFAULT_DEPTH = 3.08567758e19; // 1000 Pc
|
||||
|
||||
in vec4 vs_position;
|
||||
in vec2 psfCoords;
|
||||
flat in vec3 ge_color;
|
||||
flat in float ge_screenSpaceDepth;
|
||||
|
||||
Fragment getFragment() {
|
||||
|
||||
vec4 color = vec4(0.0);
|
||||
|
||||
// BILLBOARDS
|
||||
// Sample color. Tonemapping done in first shader pass.
|
||||
vec4 textureColor = texture( renderedTexture, uv );
|
||||
|
||||
// Use the following to check for any intensity at all.
|
||||
//color = (length(intensity.rgb) > 0.001) ? vec4(1.0) : vec4(0.0);
|
||||
|
||||
Fragment frag;
|
||||
|
||||
vec4 textureColor = texture(psfTexture, 0.5*psfCoords + 0.5);
|
||||
vec4 fullColor = vec4(ge_color*textureColor.a, textureColor.a);
|
||||
if (fullColor.a == 0) {
|
||||
discard;
|
||||
}
|
||||
frag.color = fullColor;
|
||||
|
||||
frag.depth = ge_screenSpaceDepth;
|
||||
frag.gPosition = vs_position;
|
||||
frag.color = textureColor;
|
||||
// Place stars at back to begin with.
|
||||
frag.depth = DEFAULT_DEPTH;
|
||||
frag.gNormal = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
frag.blend = BLEND_MODE_NORMAL;
|
||||
|
||||
return frag;
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2020 *
|
||||
* *
|
||||
* 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 "fragment.glsl"
|
||||
|
||||
in vec2 uv;
|
||||
|
||||
uniform sampler2D renderedTexture;
|
||||
uniform dmat4 projection;
|
||||
uniform vec2 screenSize;
|
||||
uniform int filterSize;
|
||||
uniform float sigma;
|
||||
uniform float pixelWeightThreshold;
|
||||
|
||||
const float M_PI = 3.141592653589793238462;
|
||||
const float DEFAULT_DEPTH = 3.08567758e19; // 1000 Pc
|
||||
|
||||
Fragment getFragment() {
|
||||
|
||||
vec4 color = vec4(0.0);
|
||||
|
||||
// GL_POINTS
|
||||
|
||||
// Use frustum params to be able to compensate for a skewed frustum (in a dome).
|
||||
float near = float(projection[3][2] / (projection[2][2] - 1.0));
|
||||
float left = float(near * (projection[2][0] - 1.0) / projection[0][0]);
|
||||
float right = float(near * (projection[2][0] + 1.0) / projection[0][0]);
|
||||
float top = float(near * (projection[2][1] + 1.0) / projection[1][1]);
|
||||
float bottom = float(near * (projection[2][1] - 1.0) / projection[1][1]);
|
||||
|
||||
float xFactor = float(projection[0][0]);
|
||||
float yFactor = float(projection[1][1]);
|
||||
|
||||
float planeAspect = yFactor / xFactor; // Equals: (right - left) / (top - bottom)
|
||||
float screenAspect = screenSize.x / screenSize.y;
|
||||
float fullAspect = planeAspect / screenAspect;
|
||||
|
||||
// Find screenPos in skewed frustum. uv is [0, 1]
|
||||
vec2 screenPos = uv * vec2(right - left, top - bottom) + vec2(left, bottom);
|
||||
|
||||
// Find our elliptic scale factors by trigonometric approximation.
|
||||
float beta = atan(length(screenPos) / near);
|
||||
vec2 sigmaScaleFactor = vec2( 1.0 / cos(beta), 1.0 / pow(cos(beta), 2.0));
|
||||
|
||||
float defaultScreen = 1200.0;
|
||||
float scaling = screenSize.y / defaultScreen * yFactor;
|
||||
|
||||
// Scale filter size depending on screen pos.
|
||||
vec2 filterScaleFactor = vec2(
|
||||
pow(screenPos.x / near, 2.0) * fullAspect,
|
||||
pow(screenPos.y / near, 2.0)
|
||||
);
|
||||
|
||||
// Use to ignore scaling.
|
||||
//filterScaleFactor = vec2(0.0);
|
||||
//scaling = 1.0;
|
||||
//sigmaScaleFactor = vec2(1.0);
|
||||
|
||||
// Use the following to find the origo in a skewed frustum.
|
||||
//Fragment origoFrag;
|
||||
//vec2 screenOrigo = vec2(-left, -bottom) / vec2(right - left, top - bottom);
|
||||
//if (abs(screenOrigo.x - uv.x) > 0.0005 && abs(screenOrigo.y - uv.y) > 0.0005) {
|
||||
// origoFrag.color = vec4(0.0);
|
||||
//}
|
||||
//else {
|
||||
// origoFrag.color = vec4(1.0);
|
||||
//}
|
||||
//return origoFrag;
|
||||
|
||||
// Uncomment to compare to original filterSize (assumes origo in center of screen).
|
||||
//screenPos = (uv - 0.5) * 2.0; // [-1, 1]
|
||||
//filterScaleFactor = vec2(
|
||||
// pow(screenPos.x, 2.0),
|
||||
// pow(screenPos.y, 2.0)
|
||||
//);
|
||||
|
||||
// Make use of the following flag this to toggle betweeen circular and elliptic distribution.
|
||||
bool useCircleDist = false;
|
||||
|
||||
// Apply scaling on bloom filter.
|
||||
vec2 newFilterSize = vec2(filterSize) * (1.0 + length(filterScaleFactor)) * scaling;
|
||||
|
||||
// Calculate params for a rotated Elliptic Gaussian distribution.
|
||||
float sigmaMajor;
|
||||
float sigmaMinor;
|
||||
float a;
|
||||
float b;
|
||||
float c;
|
||||
if (!useCircleDist) {
|
||||
float alpha = atan(screenPos.y, screenPos.x);
|
||||
// Apply scaling on sigma.
|
||||
sigmaMajor = sigma * sigmaScaleFactor.y * scaling;
|
||||
sigmaMinor = sigma * sigmaScaleFactor.x * scaling;
|
||||
|
||||
a = pow(cos(alpha), 2.0) / (2 * pow(sigmaMajor, 2.0))
|
||||
+ pow(sin(alpha), 2.0) / (2 * pow(sigmaMinor, 2.0)) ;
|
||||
b = sin(2 * alpha) / (4 * pow(sigmaMajor, 2.0))
|
||||
- sin(2 * alpha) / (4 * pow(sigmaMinor, 2.0)) ;
|
||||
c = pow(sin(alpha), 2.0) / (2 * pow(sigmaMajor, 2.0))
|
||||
+ pow(cos(alpha), 2.0) / (2 * pow(sigmaMinor, 2.0)) ;
|
||||
}
|
||||
|
||||
// Get a [newFilterSize x newFilterSize] filter around our pixel. UV is [0, 1]
|
||||
vec3 intensity = vec3(0.0);
|
||||
vec2 pixelSize = 1.0 / screenSize;
|
||||
ivec2 halfFilterSize = ivec2((newFilterSize - 1.0) / 2.0);
|
||||
for (int y = -halfFilterSize.y; y <= halfFilterSize.y; y += 1) {
|
||||
for (int x = -halfFilterSize.x; x <= halfFilterSize.x; x += 1) {
|
||||
vec2 sPoint = uv + (pixelSize * ivec2(x, y));
|
||||
|
||||
// Calculate the contribution of this pixel (elliptic gaussian distribution).
|
||||
float pixelWeight = exp(-(
|
||||
a * pow(x * fullAspect, 2.0)
|
||||
+ 2 * b * x * y * fullAspect
|
||||
+ c * pow(y, 2.0)
|
||||
));
|
||||
|
||||
// Only sample inside FBO texture and if the pixel will contribute to final color.
|
||||
if (all(greaterThan(sPoint, vec2(0.0))) && all(lessThan(sPoint, vec2(1.0)))
|
||||
&& pixelWeight > pixelWeightThreshold) {
|
||||
vec4 sIntensity = texture( renderedTexture, sPoint );
|
||||
|
||||
// Use normal distribution function for halo/bloom effect.
|
||||
if (useCircleDist) {
|
||||
float circleDist = sqrt(pow(x / (1 + length(filterScaleFactor)), 2.0)
|
||||
+ pow(y / (1 + length(filterScaleFactor)), 2.0));
|
||||
intensity += sIntensity.rgb * (1.0 / (sigma * sqrt(2.0 * M_PI))) *
|
||||
exp(-(pow(circleDist, 2.0) / (2.0 * pow(sigma, 2.0)))) / filterSize;
|
||||
}
|
||||
else {
|
||||
// Divide contribution by area of ellipse.
|
||||
intensity += sIntensity.rgb * pixelWeight * fullAspect;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Tonemap intensity to color!
|
||||
//intensity = 1.0 - 1.0 * exp(-25.0 * intensity);
|
||||
intensity = pow(intensity, vec3(0.8));
|
||||
|
||||
if (length(intensity) < 0.01) {
|
||||
discard;
|
||||
}
|
||||
|
||||
color = vec4(intensity, 1.0f);
|
||||
|
||||
// Use the following to check for any intensity at all.
|
||||
//color = (length(intensity.rgb) > 0.001) ? vec4(1.0) : vec4(0.0);
|
||||
|
||||
Fragment frag;
|
||||
frag.color = color;
|
||||
// Place stars at back to begin with.
|
||||
frag.depth = DEFAULT_DEPTH;
|
||||
frag.gNormal = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
frag.blend = BLEND_MODE_NORMAL;
|
||||
|
||||
return frag;
|
||||
}
|
||||
+4
-6
@@ -24,13 +24,11 @@
|
||||
|
||||
#version __CONTEXT__
|
||||
|
||||
layout(location = 0) in vec3 in_position;
|
||||
layout(location = 1) in vec3 in_color;
|
||||
in vec3 in_position;
|
||||
|
||||
out vec3 vs_color;
|
||||
out vec2 uv;
|
||||
|
||||
void main() {
|
||||
vs_color = in_color;
|
||||
|
||||
gl_Position = vec4(in_position, 1.0);
|
||||
uv = (in_position.xy + 1.0) / 2.0;
|
||||
gl_Position = vec4(in_position, 1.0);
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2020 *
|
||||
* *
|
||||
* 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__
|
||||
|
||||
#include "floatoperations.glsl"
|
||||
|
||||
// Keep in sync with gaiaoptions.h:RenderOption enum
|
||||
const int RENDEROPTION_STATIC = 0;
|
||||
const int RENDEROPTION_COLOR = 1;
|
||||
const int RENDEROPTION_MOTION = 2;
|
||||
const float EPS = 1e-5;
|
||||
const float Parsec = 3.0856776e16;
|
||||
|
||||
in vec3 in_position;
|
||||
in vec2 in_brightness;
|
||||
in vec3 in_velocity;
|
||||
|
||||
out vec2 vs_brightness;
|
||||
out vec4 vs_gPosition;
|
||||
out float vs_starDistFromSun;
|
||||
out float vs_cameraDistFromSun;
|
||||
|
||||
uniform dmat4 model;
|
||||
uniform dmat4 view;
|
||||
uniform dmat4 projection;
|
||||
uniform float time;
|
||||
uniform int renderOption;
|
||||
|
||||
uniform vec2 posXThreshold;
|
||||
uniform vec2 posYThreshold;
|
||||
uniform vec2 posZThreshold;
|
||||
uniform vec2 gMagThreshold;
|
||||
uniform vec2 bpRpThreshold;
|
||||
uniform vec2 distThreshold;
|
||||
|
||||
void main() {
|
||||
vs_brightness = in_brightness;
|
||||
|
||||
// Check if we should filter this star by position. Thres depending on original values.
|
||||
if ( (abs(posXThreshold.x) > EPS && in_position.x < posXThreshold.x) ||
|
||||
(abs(posXThreshold.y) > EPS && in_position.x > posXThreshold.y) ||
|
||||
(abs(posYThreshold.x) > EPS && in_position.y < posYThreshold.x) ||
|
||||
(abs(posYThreshold.y) > EPS && in_position.y > posYThreshold.y) ||
|
||||
(abs(posZThreshold.x) > EPS && in_position.z < posZThreshold.x) ||
|
||||
(abs(posZThreshold.y) > EPS && in_position.z > posZThreshold.y) ||
|
||||
(abs(distThreshold.x - distThreshold.y) < EPS
|
||||
&& abs(length(in_position) - distThreshold.y) < EPS) ||
|
||||
( renderOption != RENDEROPTION_STATIC && (
|
||||
(abs(gMagThreshold.x - gMagThreshold.y) < EPS && abs(gMagThreshold.x - in_brightness.x) < EPS) ||
|
||||
(abs(gMagThreshold.x - 20.0f) > EPS && in_brightness.x < gMagThreshold.x) ||
|
||||
(abs(gMagThreshold.y - 20.0f) > EPS && in_brightness.x > gMagThreshold.y) ||
|
||||
(abs(bpRpThreshold.x - bpRpThreshold.y) < EPS && abs(bpRpThreshold.x - in_brightness.y) < EPS) ||
|
||||
(abs(bpRpThreshold.x) > EPS && in_brightness.y < bpRpThreshold.x) ||
|
||||
(abs(bpRpThreshold.y) > EPS && in_brightness.y > bpRpThreshold.y))) ) {
|
||||
// Discard star in geometry shader.
|
||||
vs_gPosition = vec4(0.0);
|
||||
gl_Position = vec4(0.0);
|
||||
return;
|
||||
}
|
||||
|
||||
// Convert kiloParsec to meter.
|
||||
vec4 objectPosition = vec4(in_position * 1000 * Parsec, 1.0);
|
||||
|
||||
// Add velocity if we've read any.
|
||||
if ( renderOption == RENDEROPTION_MOTION ) {
|
||||
// Velocity is already in [m/s].
|
||||
objectPosition.xyz += time * in_velocity;
|
||||
}
|
||||
|
||||
// Thres moving stars by their new position.
|
||||
float distPosition = length(objectPosition.xyz / (1000.0 * Parsec) );
|
||||
if ( (abs(distThreshold.x - distThreshold.y) > EPS &&
|
||||
((abs(distThreshold.x) > EPS && distPosition< distThreshold.x) ||
|
||||
(abs(distThreshold.y) > EPS && distPosition > distThreshold.y))) ) {
|
||||
// Discard star in geometry shader.
|
||||
vs_gPosition = vec4(0.0);
|
||||
gl_Position = vec4(0.0);
|
||||
return;
|
||||
}
|
||||
|
||||
// Apply camera transforms.
|
||||
dvec4 viewPosition = view * model * objectPosition;
|
||||
vec4 sunPosition = vec4(view * model * vec4(0.0f, 0.0f, 0.0f, 1.0f));
|
||||
|
||||
vs_starDistFromSun = safeLength(objectPosition);
|
||||
vs_cameraDistFromSun = safeLength(sunPosition);
|
||||
|
||||
// Remove stars without position, happens when VBO chunk is stuffed with zeros.
|
||||
// Has to be done in Geometry shader because Vertices cannot be discarded here.
|
||||
if ( length(in_position) > EPS ){
|
||||
vs_gPosition = vec4(model * objectPosition);
|
||||
gl_Position = vec4(projection * viewPosition);
|
||||
}
|
||||
else {
|
||||
vs_gPosition = vec4(0.0);
|
||||
gl_Position = vec4(0.0);
|
||||
}
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2020 *
|
||||
* *
|
||||
* 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 maxStepSize#{id} = 0.1;
|
||||
uniform vec3 aspect#{id} = vec3(1.0);
|
||||
uniform float opacityCoefficient#{id} = 1.0;
|
||||
uniform float absorptionMultiply#{id} = 50.0;
|
||||
uniform float emissionMultiply#{id} = 1500.0;
|
||||
uniform sampler3D galaxyTexture#{id};
|
||||
|
||||
void sample#{id}(
|
||||
vec3 samplePos,
|
||||
vec3 dir,
|
||||
inout vec3 accumulatedColor,
|
||||
inout vec3 accumulatedAlpha,
|
||||
inout float stepSize
|
||||
) {
|
||||
vec3 aspect = aspect#{id};
|
||||
stepSize = maxStepSize#{id} / length(dir / aspect);
|
||||
|
||||
//Early ray termination on black parts of the data
|
||||
vec3 normalizedPos = samplePos * 2.f - 1.f;
|
||||
if (normalizedPos.x * normalizedPos.x + normalizedPos.y * normalizedPos.y > 0.7) {
|
||||
return;
|
||||
}
|
||||
|
||||
vec4 sampledColor = texture(galaxyTexture#{id}, samplePos.xyz);
|
||||
|
||||
// Source textures currently are square-rooted to avoid dithering in the shadows.
|
||||
// So square them back
|
||||
sampledColor = sampledColor*sampledColor;
|
||||
|
||||
// Fudge for the dust "spreading"
|
||||
sampledColor.a = clamp(sampledColor.a, 0.f, 1.f);
|
||||
sampledColor.a = pow(sampledColor.a, 0.7f);
|
||||
|
||||
// Absorption probability
|
||||
float scaledDensity = sampledColor.a * stepSize * absorptionMultiply#{id};
|
||||
vec3 alphaTint = vec3(0.3f, 0.54f, 0.85f);
|
||||
vec3 absorption = alphaTint * scaledDensity;
|
||||
|
||||
// Extinction
|
||||
vec3 extinction = exp(-absorption);
|
||||
accumulatedColor.rgb *= extinction;
|
||||
|
||||
// Emission
|
||||
accumulatedColor.rgb +=
|
||||
sampledColor.rgb * stepSize * emissionMultiply#{id} * opacityCoefficient#{id};
|
||||
|
||||
vec3 oneMinusFrontAlpha = vec3(1.f) - accumulatedAlpha;
|
||||
accumulatedAlpha += oneMinusFrontAlpha * sampledColor.rgb * opacityCoefficient#{id};
|
||||
}
|
||||
|
||||
float stepSize#{id}(vec3 samplePos, vec3 dir) {
|
||||
return maxStepSize#{id} * length(dir * 1.f / aspect#{id});
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2020 *
|
||||
* *
|
||||
* 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 "fragment.glsl"
|
||||
#include "floatoperations.glsl"
|
||||
|
||||
in vec4 vs_position;
|
||||
in vec3 vs_color;
|
||||
in float vs_screenSpaceDepth;
|
||||
in float vs_starBrightness;
|
||||
|
||||
uniform float opacityCoefficient;
|
||||
|
||||
Fragment getFragment() {
|
||||
Fragment frag;
|
||||
|
||||
float multipliedOpacityCoefficient = opacityCoefficient*opacityCoefficient;
|
||||
vec3 extinction = exp(vec3(0.6, 0.2, 0.3) - vs_color);
|
||||
vec4 fullColor = vec4(vs_color*extinction*vs_starBrightness*multipliedOpacityCoefficient, opacityCoefficient);
|
||||
frag.color = fullColor;
|
||||
|
||||
frag.depth = vs_screenSpaceDepth;
|
||||
frag.gPosition = vs_position;
|
||||
frag.gNormal = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
|
||||
return frag;
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2020 *
|
||||
* *
|
||||
* 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 "floatoperations.glsl"
|
||||
#include "fragment.glsl"
|
||||
|
||||
in vec3 modelPosition;
|
||||
in vec4 viewPosition;
|
||||
|
||||
Fragment getFragment() {
|
||||
Fragment frag;
|
||||
//Early ray termination on black parts of the data
|
||||
/*vec3 normalizedPos = (modelPosition*2.0)-1.0;
|
||||
if (abs(modelPosition.x) > 0.9 || abs(modelPosition.y) > 0.9) {
|
||||
frag.color = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
else {*/
|
||||
vec3 pos = modelPosition + 0.5;
|
||||
//vec3 posClamp = clamp(pos, vec3(0.0), vec3(1.0));
|
||||
frag.color = vec4(pos, 1.0);
|
||||
//}
|
||||
|
||||
frag.depth = safeLength(viewPosition);
|
||||
return frag;
|
||||
}
|
||||
@@ -22,29 +22,51 @@
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#include <modules/galaxy/galaxymodule.h>
|
||||
#include <modules/gaia/gaiamodule.h>
|
||||
|
||||
#include <modules/galaxy/rendering/renderablegalaxy.h>
|
||||
#include <modules/galaxy/tasks/milkywayconversiontask.h>
|
||||
#include <modules/galaxy/tasks/milkywaypointsconversiontask.h>
|
||||
#include <modules/gaia/tasks/constructoctreetask.h>
|
||||
#include <modules/gaia/rendering/renderablegaiastars.h>
|
||||
#include <modules/gaia/tasks/readfitstask.h>
|
||||
#include <modules/gaia/tasks/readspecktask.h>
|
||||
#include <openspace/documentation/documentation.h>
|
||||
#include <openspace/rendering/renderable.h>
|
||||
#include <openspace/scripting/lualibrary.h>
|
||||
#include <openspace/util/factorymanager.h>
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <ghoul/misc/assert.h>
|
||||
#include <ghoul/misc/templatefactory.h>
|
||||
|
||||
namespace openspace {
|
||||
|
||||
GalaxyModule::GalaxyModule() : OpenSpaceModule(Name) {}
|
||||
GaiaModule::GaiaModule() : OpenSpaceModule(Name) {}
|
||||
|
||||
void GalaxyModule::internalInitialize(const ghoul::Dictionary&) {
|
||||
void GaiaModule::internalInitialize(const ghoul::Dictionary&) {
|
||||
auto fRenderable = FactoryManager::ref().factory<Renderable>();
|
||||
ghoul_assert(fRenderable, "No renderable factory existed");
|
||||
fRenderable->registerClass<RenderableGalaxy>("RenderableGalaxy");
|
||||
fRenderable->registerClass<RenderableGaiaStars>("RenderableGaiaStars");
|
||||
|
||||
auto fTask = FactoryManager::ref().factory<Task>();
|
||||
ghoul_assert(fRenderable, "No task factory existed");
|
||||
fTask->registerClass<MilkywayConversionTask>("MilkywayConversionTask");
|
||||
fTask->registerClass<MilkywayPointsConversionTask>("MilkywayPointsConversionTask");
|
||||
fTask->registerClass<ReadFitsTask>("ReadFitsTask");
|
||||
fTask->registerClass<ReadSpeckTask>("ReadSpeckTask");
|
||||
fTask->registerClass<ConstructOctreeTask>("ConstructOctreeTask");
|
||||
}
|
||||
|
||||
std::vector<documentation::Documentation> GaiaModule::documentations() const {
|
||||
return {
|
||||
RenderableGaiaStars::Documentation(),
|
||||
ReadFitsTask::Documentation(),
|
||||
ReadSpeckTask::Documentation(),
|
||||
ConstructOctreeTask::Documentation(),
|
||||
};
|
||||
}
|
||||
|
||||
scripting::LuaLibrary GaiaModule::luaLibrary() const {
|
||||
scripting::LuaLibrary res;
|
||||
res.name = "gaia";
|
||||
res.scripts = {
|
||||
absPath("${MODULE_GAIA}/scripts/filtering.lua")
|
||||
};
|
||||
return res;
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -22,18 +22,24 @@
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#ifndef __OPENSPACE_MODULE_GALAXY___GALAXYMODULE___H__
|
||||
#define __OPENSPACE_MODULE_GALAXY___GALAXYMODULE___H__
|
||||
#ifndef __OPENSPACE_MODULE_GAIA___GAIAMODULE___H__
|
||||
#define __OPENSPACE_MODULE_GAIA___GAIAMODULE___H__
|
||||
|
||||
#include <openspace/util/openspacemodule.h>
|
||||
|
||||
#include <openspace/documentation/documentation.h>
|
||||
|
||||
namespace openspace {
|
||||
|
||||
class GalaxyModule : public OpenSpaceModule {
|
||||
class GaiaModule : public OpenSpaceModule {
|
||||
public:
|
||||
constexpr static const char* Name = "Galaxy";
|
||||
constexpr static const char* Name = "Gaia";
|
||||
|
||||
GalaxyModule();
|
||||
GaiaModule();
|
||||
virtual ~GaiaModule() = default;
|
||||
|
||||
std::vector<documentation::Documentation> documentations() const override;
|
||||
scripting::LuaLibrary luaLibrary() const override;
|
||||
|
||||
private:
|
||||
void internalInitialize(const ghoul::Dictionary&) override;
|
||||
@@ -41,4 +47,4 @@ private:
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
#endif // __OPENSPACE_MODULE_GALAXY___GALAXYMODULE___H__
|
||||
#endif // __OPENSPACE_MODULE_GAIA___GAIAMODULE___H__
|
||||
|
||||
@@ -0,0 +1,816 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2020 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
|
||||
* software and associated documentation files (the "Software"), to deal in the Software *
|
||||
* without restriction, including without limitation the rights to use, copy, modify, *
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
|
||||
* permit persons to whom the Software is furnished to do so, subject to the following *
|
||||
* conditions: *
|
||||
* *
|
||||
* The above copyright notice and this permission notice shall be included in all copies *
|
||||
* or substantial portions of the Software. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#include <modules/gaia/tasks/constructoctreetask.h>
|
||||
|
||||
#include <openspace/documentation/documentation.h>
|
||||
#include <openspace/documentation/verifier.h>
|
||||
#include <ghoul/fmt.h>
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <ghoul/filesystem/directory.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/misc/dictionary.h>
|
||||
#include <fstream>
|
||||
#include <thread>
|
||||
|
||||
namespace {
|
||||
constexpr const char* KeyInFileOrFolderPath = "InFileOrFolderPath";
|
||||
constexpr const char* KeyOutFileOrFolderPath = "OutFileOrFolderPath";
|
||||
constexpr const char* KeyMaxDist = "MaxDist";
|
||||
constexpr const char* KeyMaxStarsPerNode = "MaxStarsPerNode";
|
||||
constexpr const char* KeySingleFileInput = "SingleFileInput";
|
||||
|
||||
constexpr const char* KeyFilterPosX = "FilterPosX";
|
||||
constexpr const char* KeyFilterPosY = "FilterPosY";
|
||||
constexpr const char* KeyFilterPosZ = "FilterPosZ";
|
||||
constexpr const char* KeyFilterGMag = "FilterGMag";
|
||||
constexpr const char* KeyFilterBpRp = "FilterBpRp";
|
||||
constexpr const char* KeyFilterVelX = "FilterVelX";
|
||||
constexpr const char* KeyFilterVelY = "FilterVelY";
|
||||
constexpr const char* KeyFilterVelZ = "FilterVelZ";
|
||||
constexpr const char* KeyFilterBpMag = "FilterBpMag";
|
||||
constexpr const char* KeyFilterRpMag = "FilterRpMag";
|
||||
constexpr const char* KeyFilterBpG = "FilterBpG";
|
||||
constexpr const char* KeyFilterGRp = "FilterGRp";
|
||||
constexpr const char* KeyFilterRa = "FilterRa";
|
||||
constexpr const char* KeyFilterRaError = "FilterRaError";
|
||||
constexpr const char* KeyFilterDec = "FilterDec";
|
||||
constexpr const char* KeyFilterDecError = "FilterDecError";
|
||||
constexpr const char* KeyFilterParallax = "FilterParallax";
|
||||
constexpr const char* KeyFilterParallaxError = "FilterParallaxError";
|
||||
constexpr const char* KeyFilterPmra = "FilterPmra";
|
||||
constexpr const char* KeyFilterPmraError = "FilterPmraError";
|
||||
constexpr const char* KeyFilterPmdec = "FilterPmdec";
|
||||
constexpr const char* KeyFilterPmdecError = "FilterPmdecError";
|
||||
constexpr const char* KeyFilterRv = "FilterRv";
|
||||
constexpr const char* KeyFilterRvError = "FilterRvError";
|
||||
|
||||
constexpr const char* _loggerCat = "ConstructOctreeTask";
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
ConstructOctreeTask::ConstructOctreeTask(const ghoul::Dictionary& dictionary) {
|
||||
openspace::documentation::testSpecificationAndThrow(
|
||||
documentation(),
|
||||
dictionary,
|
||||
"ConstructOctreeTask"
|
||||
);
|
||||
|
||||
_inFileOrFolderPath = absPath(dictionary.value<std::string>(KeyInFileOrFolderPath));
|
||||
_outFileOrFolderPath = absPath(dictionary.value<std::string>(KeyOutFileOrFolderPath));
|
||||
|
||||
if (dictionary.hasKey(KeyMaxDist)) {
|
||||
_maxDist = static_cast<int>(dictionary.value<double>(KeyMaxDist));
|
||||
}
|
||||
|
||||
if (dictionary.hasKey(KeyMaxStarsPerNode)) {
|
||||
_maxStarsPerNode = static_cast<int>(dictionary.value<double>(KeyMaxStarsPerNode));
|
||||
}
|
||||
|
||||
if (dictionary.hasKey(KeySingleFileInput)) {
|
||||
_singleFileInput = dictionary.value<bool>(KeySingleFileInput);
|
||||
}
|
||||
|
||||
_octreeManager = std::make_shared<OctreeManager>();
|
||||
_indexOctreeManager = std::make_shared<OctreeManager>();
|
||||
|
||||
// Check for filter params.
|
||||
if (dictionary.hasKey(KeyFilterPosX)) {
|
||||
_posX = dictionary.value<glm::vec2>(KeyFilterPosX);
|
||||
_filterPosX = true;
|
||||
}
|
||||
if (dictionary.hasKey(KeyFilterPosY)) {
|
||||
_posY = dictionary.value<glm::vec2>(KeyFilterPosY);
|
||||
_filterPosY = true;
|
||||
}
|
||||
if (dictionary.hasKey(KeyFilterPosZ)) {
|
||||
_posZ = dictionary.value<glm::vec2>(KeyFilterPosZ);
|
||||
_filterPosZ = true;
|
||||
}
|
||||
if (dictionary.hasKey(KeyFilterGMag)) {
|
||||
_gMag = dictionary.value<glm::vec2>(KeyFilterGMag);
|
||||
_filterGMag = true;
|
||||
}
|
||||
if (dictionary.hasKey(KeyFilterBpRp)) {
|
||||
_bpRp = dictionary.value<glm::vec2>(KeyFilterBpRp);
|
||||
_filterBpRp = true;
|
||||
}
|
||||
if (dictionary.hasKey(KeyFilterVelX)) {
|
||||
_velX = dictionary.value<glm::vec2>(KeyFilterVelX);
|
||||
_filterVelX = true;
|
||||
}
|
||||
if (dictionary.hasKey(KeyFilterVelY)) {
|
||||
_velY = dictionary.value<glm::vec2>(KeyFilterVelY);
|
||||
_filterVelY = true;
|
||||
}
|
||||
if (dictionary.hasKey(KeyFilterVelZ)) {
|
||||
_velZ = dictionary.value<glm::vec2>(KeyFilterVelZ);
|
||||
_filterVelZ = true;
|
||||
}
|
||||
if (dictionary.hasKey(KeyFilterBpMag)) {
|
||||
_bpMag = dictionary.value<glm::vec2>(KeyFilterBpMag);
|
||||
_filterBpMag = true;
|
||||
}
|
||||
if (dictionary.hasKey(KeyFilterRpMag)) {
|
||||
_rpMag = dictionary.value<glm::vec2>(KeyFilterRpMag);
|
||||
_filterRpMag = true;
|
||||
}
|
||||
if (dictionary.hasKey(KeyFilterBpG)) {
|
||||
_bpG = dictionary.value<glm::vec2>(KeyFilterBpG);
|
||||
_filterBpG = true;
|
||||
}
|
||||
if (dictionary.hasKey(KeyFilterGRp)) {
|
||||
_gRp = dictionary.value<glm::vec2>(KeyFilterGRp);
|
||||
_filterGRp = true;
|
||||
}
|
||||
if (dictionary.hasKey(KeyFilterRa)) {
|
||||
_ra = dictionary.value<glm::vec2>(KeyFilterRa);
|
||||
_filterRa = true;
|
||||
}
|
||||
if (dictionary.hasKey(KeyFilterRaError)) {
|
||||
_raError = dictionary.value<glm::vec2>(KeyFilterRaError);
|
||||
_filterRaError = true;
|
||||
}
|
||||
if (dictionary.hasKey(KeyFilterDec)) {
|
||||
_dec = dictionary.value<glm::vec2>(KeyFilterDec);
|
||||
_filterDec = true;
|
||||
}
|
||||
if (dictionary.hasKey(KeyFilterDecError)) {
|
||||
_decError = dictionary.value<glm::vec2>(KeyFilterDecError);
|
||||
_filterDecError = true;
|
||||
}
|
||||
if (dictionary.hasKey(KeyFilterParallax)) {
|
||||
_parallax = dictionary.value<glm::vec2>(KeyFilterParallax);
|
||||
_filterParallax = true;
|
||||
}
|
||||
if (dictionary.hasKey(KeyFilterParallaxError)) {
|
||||
_parallaxError = dictionary.value<glm::vec2>(KeyFilterParallaxError);
|
||||
_filterParallaxError = true;
|
||||
}
|
||||
if (dictionary.hasKey(KeyFilterPmra)) {
|
||||
_pmra = dictionary.value<glm::vec2>(KeyFilterPmra);
|
||||
_filterPmra = true;
|
||||
}
|
||||
if (dictionary.hasKey(KeyFilterPmraError)) {
|
||||
_pmraError = dictionary.value<glm::vec2>(KeyFilterPmraError);
|
||||
_filterPmraError = true;
|
||||
}
|
||||
if (dictionary.hasKey(KeyFilterPmdec)) {
|
||||
_pmdec = dictionary.value<glm::vec2>(KeyFilterPmdec);
|
||||
_filterPmdec = true;
|
||||
}
|
||||
if (dictionary.hasKey(KeyFilterPmdecError)) {
|
||||
_pmdecError = dictionary.value<glm::vec2>(KeyFilterPmdecError);
|
||||
_filterPmdecError = true;
|
||||
}
|
||||
if (dictionary.hasKey(KeyFilterRv)) {
|
||||
_rv = dictionary.value<glm::vec2>(KeyFilterRv);
|
||||
_filterRv = true;
|
||||
}
|
||||
if (dictionary.hasKey(KeyFilterRvError)) {
|
||||
_rvError = dictionary.value<glm::vec2>(KeyFilterRvError);
|
||||
_filterRvError = true;
|
||||
}
|
||||
}
|
||||
|
||||
std::string ConstructOctreeTask::description() {
|
||||
return "Read bin file (or files in folder): " + _inFileOrFolderPath + "\n "
|
||||
"and write octree data file (or files) into: " + _outFileOrFolderPath + "\n";
|
||||
}
|
||||
|
||||
void ConstructOctreeTask::perform(const Task::ProgressCallback& onProgress) {
|
||||
onProgress(0.0f);
|
||||
|
||||
if (_singleFileInput) {
|
||||
constructOctreeFromSingleFile(onProgress);
|
||||
}
|
||||
else {
|
||||
constructOctreeFromFolder(onProgress);
|
||||
}
|
||||
|
||||
onProgress(1.0f);
|
||||
}
|
||||
|
||||
void ConstructOctreeTask::constructOctreeFromSingleFile(
|
||||
const Task::ProgressCallback& progressCallback)
|
||||
{
|
||||
std::vector<float> fullData;
|
||||
int32_t nValues = 0;
|
||||
int32_t nValuesPerStar = 0;
|
||||
size_t nFilteredStars = 0;
|
||||
int nTotalStars = 0;
|
||||
|
||||
_octreeManager->initOctree(0, _maxDist, _maxStarsPerNode);
|
||||
|
||||
LINFO("Reading data file: " + _inFileOrFolderPath);
|
||||
|
||||
LINFO(fmt::format(
|
||||
"MAX DIST: {} - MAX STARS PER NODE: {}",
|
||||
_octreeManager->maxDist(), _octreeManager->maxStarsPerNode()
|
||||
));
|
||||
|
||||
// Use to generate a synthetic dataset
|
||||
/*for (float z = -1.0; z < 1.0; z += 0.05) {
|
||||
for (float y = -1.0; y < 1.0; y += 0.05) {
|
||||
for (float x = -1.0; x < 1.0; x += 0.05) {
|
||||
float r = static_cast <float> (rand()) / static_cast <float> (RAND_MAX);
|
||||
std::vector<float> renderValues(8);
|
||||
renderValues[0] = x; // + x * r;
|
||||
renderValues[2] = z; // + y * r;
|
||||
renderValues[1] = y; // + z * r;
|
||||
renderValues[3] = 5.0; // + 10 * r;
|
||||
renderValues[4] = 2.0; // + 10 * r;
|
||||
renderValues[5] = r;
|
||||
renderValues[6] = r;
|
||||
renderValues[7] = r;
|
||||
_octreeManager->insert(renderValues);
|
||||
nTotalStars++;
|
||||
nValues+=8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (float phi = -180.0; phi < 180.0; phi += 10.0) {
|
||||
for (float theta = -90.0; theta <= 90.0; theta += 10.0) {
|
||||
float r = 1.0;
|
||||
std::vector<float> renderValues(8);
|
||||
renderValues[0] = r * sin(glm::radians(theta)) * cos(glm::radians(phi));
|
||||
renderValues[2] = r * sin(glm::radians(theta)) * sin(glm::radians(phi));
|
||||
renderValues[1] = r * cos(glm::radians(theta));
|
||||
renderValues[3] = 5.0;
|
||||
renderValues[4] = 2.0;
|
||||
renderValues[5] = r;
|
||||
renderValues[6] = r;
|
||||
renderValues[7] = r;
|
||||
_octreeManager->insert(renderValues);
|
||||
nTotalStars++;
|
||||
nValues += 8;
|
||||
}
|
||||
}*/
|
||||
|
||||
std::ifstream inFileStream(_inFileOrFolderPath, std::ifstream::binary);
|
||||
if (inFileStream.good()) {
|
||||
inFileStream.read(reinterpret_cast<char*>(&nValues), sizeof(int32_t));
|
||||
inFileStream.read(reinterpret_cast<char*>(&nValuesPerStar), sizeof(int32_t));
|
||||
|
||||
fullData.resize(nValues);
|
||||
inFileStream.read(
|
||||
reinterpret_cast<char*>(fullData.data()),
|
||||
nValues * sizeof(fullData[0])
|
||||
);
|
||||
nTotalStars = nValues / nValuesPerStar;
|
||||
|
||||
progressCallback(0.3f);
|
||||
LINFO("Constructing Octree.");
|
||||
|
||||
// Insert star into octree. We assume the data already is in correct order.
|
||||
for (size_t i = 0; i < fullData.size(); i += nValuesPerStar) {
|
||||
auto first = fullData.begin() + i;
|
||||
auto last = fullData.begin() + i + nValuesPerStar;
|
||||
std::vector<float> filterValues(first, last);
|
||||
std::vector<float> renderValues(first, first + RENDER_VALUES);
|
||||
|
||||
// Filter data by parameters.
|
||||
if (checkAllFilters(filterValues)) {
|
||||
nFilteredStars++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// If all filters passed then insert render values into Octree.
|
||||
_octreeManager->insert(renderValues);
|
||||
}
|
||||
inFileStream.close();
|
||||
}
|
||||
else {
|
||||
LERROR(fmt::format(
|
||||
"Error opening file '{}' for loading preprocessed file!",
|
||||
_inFileOrFolderPath
|
||||
));
|
||||
}
|
||||
LINFO(fmt::format("{} of {} read stars were filtered", nFilteredStars, nTotalStars));
|
||||
|
||||
// Slice LOD data before writing to files.
|
||||
_octreeManager->sliceLodData();
|
||||
|
||||
LINFO("Writing octree to: " + _outFileOrFolderPath);
|
||||
std::ofstream outFileStream(_outFileOrFolderPath, std::ofstream::binary);
|
||||
if (outFileStream.good()) {
|
||||
if (nValues == 0) {
|
||||
LERROR("Error writing file - No values were read from file.");
|
||||
}
|
||||
_octreeManager->writeToFile(outFileStream, true);
|
||||
|
||||
outFileStream.close();
|
||||
}
|
||||
else {
|
||||
LERROR(fmt::format(
|
||||
"Error opening file: {} as output data file.", _outFileOrFolderPath
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
void ConstructOctreeTask::constructOctreeFromFolder(
|
||||
const Task::ProgressCallback& progressCallback)
|
||||
{
|
||||
int32_t nStars = 0;
|
||||
int32_t nValuesPerStar = 0;
|
||||
size_t nFilteredStars = 0;
|
||||
//float maxRadius = 0.0;
|
||||
//int starsOutside10 = 0;
|
||||
//int starsOutside25 = 0;
|
||||
//int starsOutside50 = 0;
|
||||
//int starsOutside75 = 0;
|
||||
//int starsOutside100 = 0;
|
||||
//int starsOutside200 = 0;
|
||||
//int starsOutside300 = 0;
|
||||
//int starsOutside400 = 0;
|
||||
//int starsOutside500 = 0;
|
||||
//int starsOutside750 = 0;
|
||||
//int starsOutside1000 = 0;
|
||||
//int starsOutside1500 = 0;
|
||||
//int starsOutside2000 = 0;
|
||||
//int starsOutside5000 = 0;
|
||||
|
||||
ghoul::filesystem::Directory currentDir(_inFileOrFolderPath);
|
||||
std::vector<std::string> allInputFiles = currentDir.readFiles();
|
||||
std::vector<float> filterValues;
|
||||
auto writeThreads = std::vector<std::thread>(8);
|
||||
|
||||
_indexOctreeManager->initOctree(0, _maxDist, _maxStarsPerNode);
|
||||
|
||||
float processOneFile = 1.f / allInputFiles.size();
|
||||
|
||||
LINFO(fmt::format(
|
||||
"MAX DIST: {} - MAX STARS PER NODE: {}",
|
||||
_indexOctreeManager->maxDist(), _indexOctreeManager->maxStarsPerNode()
|
||||
));
|
||||
|
||||
for (size_t idx = 0; idx < allInputFiles.size(); ++idx) {
|
||||
std::string inFilePath = allInputFiles[idx];
|
||||
int nStarsInfile = 0;
|
||||
|
||||
LINFO("Reading data file: " + inFilePath);
|
||||
|
||||
std::ifstream inFileStream(inFilePath, std::ifstream::binary);
|
||||
if (inFileStream.good()) {
|
||||
inFileStream.read(reinterpret_cast<char*>(&nValuesPerStar), sizeof(int32_t));
|
||||
filterValues.resize(nValuesPerStar, 0.f);
|
||||
|
||||
while (inFileStream.read(
|
||||
reinterpret_cast<char*>(filterValues.data()),
|
||||
nValuesPerStar * sizeof(filterValues[0])
|
||||
))
|
||||
{
|
||||
// Filter data by parameters.
|
||||
if (checkAllFilters(filterValues)) {
|
||||
nFilteredStars++;
|
||||
continue;
|
||||
}
|
||||
// Generate a 50/12,5 dataset (gMag <=13/>13).
|
||||
//if ((filterStar(glm::vec2(20.0), filterValues[3], 20.f)) ||
|
||||
// (filterStar(glm::vec2(0.0), filterValues[16])) ||
|
||||
// (filterValues[3] > 13.0 && filterValues[17] > 0.125) ||
|
||||
// (filterValues[3] <= 13.0 && filterValues[17] > 0.5)) {
|
||||
// nFilteredStars++;
|
||||
// continue;
|
||||
//}
|
||||
|
||||
// If all filters passed then insert render values into Octree.
|
||||
std::vector<float> renderValues(
|
||||
filterValues.begin(),
|
||||
filterValues.begin() + RENDER_VALUES
|
||||
);
|
||||
|
||||
_indexOctreeManager->insert(renderValues);
|
||||
nStarsInfile++;
|
||||
|
||||
//float maxVal = fmax(fmax(fabs(renderValues[0]), fabs(renderValues[1])),
|
||||
// fabs(renderValues[2]));
|
||||
//if (maxVal > maxRadius) maxRadius = maxVal;
|
||||
//// Calculate how many stars are outside of different thresholds.
|
||||
//if (maxVal > 10) starsOutside10++;
|
||||
//if (maxVal > 25) starsOutside25++;
|
||||
//if (maxVal > 50) starsOutside50++;
|
||||
//if (maxVal > 75) starsOutside75++;
|
||||
//if (maxVal > 100) starsOutside100++;
|
||||
//if (maxVal > 200) starsOutside200++;
|
||||
//if (maxVal > 300) starsOutside300++;
|
||||
//if (maxVal > 400) starsOutside400++;
|
||||
//if (maxVal > 500) starsOutside500++;
|
||||
//if (maxVal > 750) starsOutside750++;
|
||||
//if (maxVal > 1000) starsOutside1000++;
|
||||
//if (maxVal > 1500) starsOutside1500++;
|
||||
//if (maxVal > 2000) starsOutside2000++;
|
||||
//if (maxVal > 5000) starsOutside5000++;
|
||||
}
|
||||
inFileStream.close();
|
||||
}
|
||||
else {
|
||||
LERROR(fmt::format(
|
||||
"Error opening file '{}' for loading preprocessed file!", inFilePath
|
||||
));
|
||||
}
|
||||
|
||||
// Slice LOD data.
|
||||
LINFO("Slicing LOD data!");
|
||||
_indexOctreeManager->sliceLodData(idx);
|
||||
|
||||
progressCallback((idx + 1) * processOneFile);
|
||||
nStars += nStarsInfile;
|
||||
|
||||
LINFO(fmt::format("Writing {} stars to octree files!", nStarsInfile));
|
||||
LINFO(fmt::format(
|
||||
"Number leaf nodes: {}\n Number inner nodes: {}\n Total depth of tree: {}",
|
||||
_indexOctreeManager->numLeafNodes(),
|
||||
_indexOctreeManager->numInnerNodes(),
|
||||
_indexOctreeManager->totalDepth()
|
||||
));
|
||||
|
||||
// Write to 8 separate files in a separate thread. Data will be cleared after it
|
||||
// has been written. Store joinable thread for later sync.
|
||||
std::thread t(
|
||||
&OctreeManager::writeToMultipleFiles,
|
||||
_indexOctreeManager,
|
||||
_outFileOrFolderPath,
|
||||
idx
|
||||
);
|
||||
writeThreads[idx] = std::move(t);
|
||||
}
|
||||
|
||||
LINFO(fmt::format(
|
||||
"A total of {} stars were read from files and distributed into {} total nodes",
|
||||
nStars, _indexOctreeManager->totalNodes()
|
||||
));
|
||||
LINFO(std::to_string(nFilteredStars) + " stars were filtered");
|
||||
|
||||
//LINFO("Max radius of dataset is: " + std::to_string(maxRadius) +
|
||||
// "\n Number of stars outside of:" +
|
||||
// " - 10kPc is " + std::to_string(starsOutside10) + "\n" +
|
||||
// " - 25kPc is " + std::to_string(starsOutside25) + "\n" +
|
||||
// " - 50kPc is " + std::to_string(starsOutside50) + "\n" +
|
||||
// " - 75kPc is " + std::to_string(starsOutside75) + "\n" +
|
||||
// " - 100kPc is " + std::to_string(starsOutside100) + "\n" +
|
||||
// " - 200kPc is " + std::to_string(starsOutside200) + "\n" +
|
||||
// " - 300kPc is " + std::to_string(starsOutside300) + "\n" +
|
||||
// " - 400kPc is " + std::to_string(starsOutside400) + "\n" +
|
||||
// " - 500kPc is " + std::to_string(starsOutside500) + "\n" +
|
||||
// " - 750kPc is " + std::to_string(starsOutside750) + "\n" +
|
||||
// " - 1000kPc is " + std::to_string(starsOutside1000) + "\n" +
|
||||
// " - 1500kPc is " + std::to_string(starsOutside1500) + "\n" +
|
||||
// " - 2000kPc is " + std::to_string(starsOutside2000) + "\n" +
|
||||
// " - 5000kPc is " + std::to_string(starsOutside5000));
|
||||
|
||||
// Write index file of Octree structure.
|
||||
std::string indexFileOutPath = _outFileOrFolderPath + "index.bin";
|
||||
std::ofstream outFileStream(indexFileOutPath, std::ofstream::binary);
|
||||
if (outFileStream.good()) {
|
||||
LINFO("Writing index file!");
|
||||
_indexOctreeManager->writeToFile(outFileStream, false);
|
||||
|
||||
outFileStream.close();
|
||||
}
|
||||
else {
|
||||
LERROR(fmt::format(
|
||||
"Error opening file: {} as index output file.", indexFileOutPath
|
||||
));
|
||||
}
|
||||
|
||||
// Make sure all threads are done.
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
writeThreads[i].join();
|
||||
}
|
||||
}
|
||||
|
||||
bool ConstructOctreeTask::checkAllFilters(const std::vector<float>& filterValues) {
|
||||
// Return true if star is caught in any filter.
|
||||
return (_filterPosX && filterStar(_posX, filterValues[0])) ||
|
||||
(_filterPosY && filterStar(_posY, filterValues[1])) ||
|
||||
(_filterPosZ && filterStar(_posZ, filterValues[2])) ||
|
||||
(_filterGMag && filterStar(_gMag, filterValues[3], 20.f)) ||
|
||||
(_filterBpRp && filterStar(_bpRp, filterValues[4])) ||
|
||||
(_filterVelX && filterStar(_velX, filterValues[5])) ||
|
||||
(_filterVelY && filterStar(_velY, filterValues[6])) ||
|
||||
(_filterVelZ && filterStar(_velZ, filterValues[7])) ||
|
||||
(_filterBpMag && filterStar(_bpMag, filterValues[8], 20.f)) ||
|
||||
(_filterRpMag && filterStar(_rpMag, filterValues[9], 20.f)) ||
|
||||
(_filterBpG && filterStar(_bpG, filterValues[10])) ||
|
||||
(_filterGRp && filterStar(_gRp, filterValues[11])) ||
|
||||
(_filterRa && filterStar(_ra, filterValues[12])) ||
|
||||
(_filterRaError && filterStar(_raError, filterValues[13])) ||
|
||||
(_filterDec && filterStar(_dec, filterValues[14])) ||
|
||||
(_filterDecError && filterStar(_decError, filterValues[15])) ||
|
||||
(_filterParallax && filterStar(_parallax, filterValues[16])) ||
|
||||
(_filterParallaxError && filterStar(_parallaxError, filterValues[17])) ||
|
||||
(_filterPmra && filterStar(_pmra, filterValues[18])) ||
|
||||
(_filterPmraError && filterStar(_pmraError, filterValues[19])) ||
|
||||
(_filterPmdec && filterStar(_pmdec, filterValues[20])) ||
|
||||
(_filterPmdecError && filterStar(_pmdecError, filterValues[21])) ||
|
||||
(_filterRv && filterStar(_rv, filterValues[22])) ||
|
||||
(_filterRvError && filterStar(_rvError, filterValues[23]));
|
||||
}
|
||||
|
||||
bool ConstructOctreeTask::filterStar(const glm::vec2& range, float filterValue,
|
||||
float normValue)
|
||||
{
|
||||
// Return true if star should be filtered away, i.e. if min = max = filterValue or
|
||||
// if filterValue < min (when min != 0.0) or filterValue > max (when max != 0.0).
|
||||
return (fabs(range.x - range.y) < FLT_EPSILON &&
|
||||
fabs(range.x - filterValue) < FLT_EPSILON) ||
|
||||
(fabs(range.x - normValue) > FLT_EPSILON && filterValue < range.x) ||
|
||||
(fabs(range.y - normValue) > FLT_EPSILON && filterValue > range.y);
|
||||
}
|
||||
|
||||
documentation::Documentation ConstructOctreeTask::Documentation() {
|
||||
using namespace documentation;
|
||||
return {
|
||||
"ConstructOctreeTask",
|
||||
"gaiamission_constructoctreefrombin",
|
||||
{
|
||||
{
|
||||
"Type",
|
||||
new StringEqualVerifier("ConstructOctreeTask"),
|
||||
Optional::No
|
||||
},
|
||||
{
|
||||
KeyInFileOrFolderPath,
|
||||
new StringVerifier,
|
||||
Optional::No,
|
||||
"If SingleFileInput is set to true then this specifies the path to a "
|
||||
"single BIN file containing a full dataset. Otherwise this specifies the "
|
||||
"path to a folder with multiple BIN files containing subsets of sorted "
|
||||
"star data.",
|
||||
},
|
||||
{
|
||||
KeyOutFileOrFolderPath,
|
||||
new StringVerifier,
|
||||
Optional::No,
|
||||
"If SingleFileInput is set to true then this specifies the output file "
|
||||
"name (including full path). Otherwise this specifies the path to the "
|
||||
"folder which to save all files.",
|
||||
},
|
||||
{
|
||||
KeyMaxDist,
|
||||
new IntVerifier,
|
||||
Optional::Yes,
|
||||
"If set it determines what MAX_DIST to use when creating Octree."
|
||||
},
|
||||
{
|
||||
KeyMaxStarsPerNode,
|
||||
new IntVerifier,
|
||||
Optional::Yes,
|
||||
"If set it determines what MAX_STAR_PER_NODE to use when creating Octree."
|
||||
},
|
||||
{
|
||||
KeySingleFileInput,
|
||||
new BoolVerifier,
|
||||
Optional::Yes,
|
||||
"If true then task will read from a single file and output a single "
|
||||
"binary file with the full Octree. If false then task will read all "
|
||||
"files in specified folder and output multiple files for the Octree."
|
||||
},
|
||||
{
|
||||
KeyFilterPosX,
|
||||
new Vector2Verifier<double>,
|
||||
Optional::Yes,
|
||||
"If defined then only stars with Position X values between [min, max] "
|
||||
"will be inserted into Octree (if min is set to 0.0 it is read as -Inf, "
|
||||
"if max is set to 0.0 it is read as +Inf). If min = max then all values "
|
||||
"equal min|max will be filtered away."
|
||||
},
|
||||
{
|
||||
KeyFilterPosY,
|
||||
new Vector2Verifier<double>,
|
||||
Optional::Yes,
|
||||
"If defined then only stars with Position Y values between [min, max] "
|
||||
"will be inserted into Octree (if min is set to 0.0 it is read as -Inf, "
|
||||
"if max is set to 0.0 it is read as +Inf). If min = max then all values "
|
||||
"equal min|max will be filtered away."
|
||||
},
|
||||
{
|
||||
KeyFilterPosZ,
|
||||
new Vector2Verifier<double>,
|
||||
Optional::Yes,
|
||||
"If defined then only stars with Position Z values between [min, max] "
|
||||
"will be inserted into Octree (if min is set to 0.0 it is read as -Inf, "
|
||||
"if max is set to 0.0 it is read as +Inf). If min = max then all values "
|
||||
"equal min|max will be filtered away."
|
||||
},
|
||||
{
|
||||
KeyFilterGMag,
|
||||
new Vector2Verifier<double>,
|
||||
Optional::Yes,
|
||||
"If defined then only stars with G mean magnitude values between "
|
||||
"[min, max] will be inserted into Octree (if min is set to 20.0 it is "
|
||||
"read as -Inf, if max is set to 20.0 it is read as +Inf). If min = max "
|
||||
"then all values equal min|max will be filtered away. Default "
|
||||
"GMag = 20.0 if no value existed."
|
||||
},
|
||||
{
|
||||
KeyFilterBpRp,
|
||||
new Vector2Verifier<double>,
|
||||
Optional::Yes,
|
||||
"If defined then only stars with Bp-Rp color values between [min, max] "
|
||||
"will be inserted into Octree (if min is set to 0.0 it is read as -Inf, "
|
||||
"if max is set to 0.0 it is read as +Inf). If min = max then all values "
|
||||
"equal min|max will be filtered away."
|
||||
},
|
||||
{
|
||||
KeyFilterVelX,
|
||||
new Vector2Verifier<double>,
|
||||
Optional::Yes,
|
||||
"If defined then only stars with Velocity X values between [min, max] "
|
||||
"will be inserted into Octree (if min is set to 0.0 it is read as -Inf, "
|
||||
"if max is set to 0.0 it is read as +Inf). If min = max then all values "
|
||||
"equal min|max will be filtered away."
|
||||
},
|
||||
{
|
||||
KeyFilterVelY,
|
||||
new Vector2Verifier<double>,
|
||||
Optional::Yes,
|
||||
"If defined then only stars with Velocity Y values between [min, max] "
|
||||
"will be inserted into Octree (if min is set to 0.0 it is read as -Inf, "
|
||||
"if max is set to 0.0 it is read as +Inf). If min = max then all values "
|
||||
"equal min|max will be filtered away."
|
||||
},
|
||||
{
|
||||
KeyFilterVelZ,
|
||||
new Vector2Verifier<double>,
|
||||
Optional::Yes,
|
||||
"If defined then only stars with Velocity Z values between [min, max] "
|
||||
"will be inserted into Octree (if min is set to 0.0 it is read as -Inf, "
|
||||
"if max is set to 0.0 it is read as +Inf). If min = max then all values "
|
||||
"equal min|max will be filtered away."
|
||||
},
|
||||
{
|
||||
KeyFilterBpMag,
|
||||
new Vector2Verifier<double>,
|
||||
Optional::Yes,
|
||||
"If defined then only stars with Bp mean magnitude values between "
|
||||
"[min, max] will be inserted into Octree (if min is set to 20.0 it is "
|
||||
"read as -Inf, if max is set to 20.0 it is read as +Inf). If min = max "
|
||||
"then all values equal min|max will be filtered away. Default "
|
||||
"BpMag = 20.0 if no value existed."
|
||||
},
|
||||
{
|
||||
KeyFilterRpMag,
|
||||
new Vector2Verifier<double>,
|
||||
Optional::Yes,
|
||||
"If defined then only stars with Rp mean magnitude values between "
|
||||
"[min, max] will be inserted into Octree (if min is set to 20.0 it is "
|
||||
"read as -Inf, if max is set to 20.0 it is read as +Inf). If min = max "
|
||||
"then all values equal min|max will be filtered away. Default RpMag = "
|
||||
"20.0 if no value existed."
|
||||
},
|
||||
{
|
||||
KeyFilterBpG,
|
||||
new Vector2Verifier<double>,
|
||||
Optional::Yes,
|
||||
"If defined then only stars with Bp-G color values between [min, max] "
|
||||
"will be inserted into Octree (if min is set to 0.0 it is read as -Inf, "
|
||||
"if max is set to 0.0 it is read as +Inf). If min = max then all values "
|
||||
"equal min|max will be filtered away."
|
||||
},
|
||||
{
|
||||
KeyFilterGRp,
|
||||
new Vector2Verifier<double>,
|
||||
Optional::Yes,
|
||||
"If defined then only stars with G-Rp color values between [min, max] "
|
||||
"will be inserted into Octree (if min is set to 0.0 it is read as -Inf, "
|
||||
"if max is set to 0.0 it is read as +Inf). If min = max then all values "
|
||||
"equal min|max will be filtered away."
|
||||
},
|
||||
{
|
||||
KeyFilterRa,
|
||||
new Vector2Verifier<double>,
|
||||
Optional::Yes,
|
||||
"If defined then only stars with RA values between [min, max] "
|
||||
"will be inserted into Octree (if min is set to 0.0 it is read as -Inf, "
|
||||
"if max is set to 0.0 it is read as +Inf). If min = max then all values "
|
||||
"equal min|max will be filtered away."
|
||||
},
|
||||
{
|
||||
KeyFilterRaError,
|
||||
new Vector2Verifier<double>,
|
||||
Optional::Yes,
|
||||
"If defined then only stars with RA Error values between [min, max] "
|
||||
"will be inserted into Octree (if min is set to 0.0 it is read as -Inf, "
|
||||
"if max is set to 0.0 it is read as +Inf). If min = max then all values "
|
||||
"equal min|max will be filtered away."
|
||||
},
|
||||
{
|
||||
KeyFilterDec,
|
||||
new Vector2Verifier<double>,
|
||||
Optional::Yes,
|
||||
"If defined then only stars with DEC values between [min, max] "
|
||||
"will be inserted into Octree (if min is set to 0.0 it is read as -Inf, "
|
||||
"if max is set to 0.0 it is read as +Inf). If min = max then all values "
|
||||
"equal min|max will be filtered away."
|
||||
},
|
||||
{
|
||||
KeyFilterDecError,
|
||||
new Vector2Verifier<double>,
|
||||
Optional::Yes,
|
||||
"If defined then only stars with DEC Error values between [min, max] "
|
||||
"will be inserted into Octree (if min is set to 0.0 it is read as -Inf, "
|
||||
"if max is set to 0.0 it is read as +Inf). If min = max then all values "
|
||||
"equal min|max will be filtered away."
|
||||
},
|
||||
{
|
||||
KeyFilterParallax,
|
||||
new Vector2Verifier<double>,
|
||||
Optional::Yes,
|
||||
"If defined then only stars with Parallax values between [min, max] "
|
||||
"will be inserted into Octree (if min is set to 0.0 it is read as -Inf, "
|
||||
"if max is set to 0.0 it is read as +Inf). If min = max then all values "
|
||||
"equal min|max will be filtered away."
|
||||
},
|
||||
{
|
||||
KeyFilterParallaxError,
|
||||
new Vector2Verifier<double>,
|
||||
Optional::Yes,
|
||||
"If defined then only stars with Parallax Error values between "
|
||||
"[min, max] will be inserted into Octree (if min is set to 0.0 it is "
|
||||
"read as -Inf, if max is set to 0.0 it is read as +Inf). If min = max "
|
||||
"then all values equal min|max will be filtered away."
|
||||
},
|
||||
{
|
||||
KeyFilterPmra,
|
||||
new Vector2Verifier<double>,
|
||||
Optional::Yes,
|
||||
"If defined then only stars with Proper Motion RA values between "
|
||||
"[min, max] will be inserted into Octree (if min is set to 0.0 it is "
|
||||
"read as -Inf, if max is set to 0.0 it is read as +Inf). If min = max "
|
||||
"then all values equal min|max will be filtered away."
|
||||
},
|
||||
{
|
||||
KeyFilterPmraError,
|
||||
new Vector2Verifier<double>,
|
||||
Optional::Yes,
|
||||
"If defined then only stars with Proper Motion RA Error values between "
|
||||
"[min, max] will be inserted into Octree (if min is set to 0.0 it is "
|
||||
"read as -Inf, if max is set to 0.0 it is read as +Inf). If min = max "
|
||||
"then all values equal min|max will be filtered away."
|
||||
},
|
||||
{
|
||||
KeyFilterPmdec,
|
||||
new Vector2Verifier<double>,
|
||||
Optional::Yes,
|
||||
"If defined then only stars with Proper Motion DEC values between "
|
||||
"[min, max] will be inserted into Octree (if min is set to 0.0 it is "
|
||||
"read as -Inf, if max is set to 0.0 it is read as +Inf). If min = max "
|
||||
"then all values equal min|max will be filtered away."
|
||||
},
|
||||
{
|
||||
KeyFilterPmdecError,
|
||||
new Vector2Verifier<double>,
|
||||
Optional::Yes,
|
||||
"If defined then only stars with Proper Motion DEC Error values between "
|
||||
"[min, max] will be inserted into Octree (if min is set to 0.0 it is "
|
||||
"read as -Inf, if max is set to 0.0 it is read as +Inf). If min = max "
|
||||
"then all values equal min|max will be filtered away."
|
||||
},
|
||||
{
|
||||
KeyFilterRv,
|
||||
new Vector2Verifier<double>,
|
||||
Optional::Yes,
|
||||
"If defined then only stars with Radial Velocity values between "
|
||||
"[min, max] will be inserted into Octree (if min is set to 0.0 it is "
|
||||
"read as -Inf, if max is set to 0.0 it is read as +Inf). If min = max "
|
||||
"then all values equal min|max will be filtered away."
|
||||
},
|
||||
{
|
||||
KeyFilterRvError,
|
||||
new Vector2Verifier<double>,
|
||||
Optional::Yes,
|
||||
"If defined then only stars with Radial Velocity Error values between "
|
||||
"[min, max] will be inserted into Octree (if min is set to 0.0 it is "
|
||||
"read as -Inf, if max is set to 0.0 it is read as +Inf). If min = max "
|
||||
"then all values equal min|max will be filtered away."
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
@@ -0,0 +1,143 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2020 *
|
||||
* *
|
||||
* 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_MODULE_GAIA___CONSTRUCTOCTREETASK___H__
|
||||
#define __OPENSPACE_MODULE_GAIA___CONSTRUCTOCTREETASK___H__
|
||||
|
||||
#include <openspace/util/task.h>
|
||||
|
||||
#include <modules/gaia/rendering/octreeculler.h>
|
||||
#include <modules/gaia/rendering/octreemanager.h>
|
||||
|
||||
namespace openspace {
|
||||
|
||||
namespace documentation { struct Documentation; }
|
||||
|
||||
class ConstructOctreeTask : public Task {
|
||||
public:
|
||||
ConstructOctreeTask(const ghoul::Dictionary& dictionary);
|
||||
virtual ~ConstructOctreeTask() = default;
|
||||
|
||||
std::string description() override;
|
||||
void perform(const Task::ProgressCallback& onProgress) override;
|
||||
static documentation::Documentation Documentation();
|
||||
|
||||
private:
|
||||
const int RENDER_VALUES = 8;
|
||||
|
||||
/**
|
||||
* Reads a single binary file with preprocessed star data and insert the render values
|
||||
* into an octree structure (if star data passed all defined filters).
|
||||
* Stores the entire octree in one binary file.
|
||||
*/
|
||||
void constructOctreeFromSingleFile(const Task::ProgressCallback& progressCallback);
|
||||
|
||||
/**
|
||||
* Reads binary star data from 8 preprocessed files (one per branch) in specified
|
||||
* folder, prepared by ReadFitsTask, and inserts star render data into an octree
|
||||
* (if star data passed all defined filters).
|
||||
* Stores octree structure in a binary index file and stores all render data
|
||||
* separate files, one file per node in the octree.
|
||||
*/
|
||||
void constructOctreeFromFolder(const Task::ProgressCallback& progressCallback);
|
||||
|
||||
/**
|
||||
* Checks all defined filter ranges and \returns true if any of the corresponding
|
||||
* <code>filterValues</code> are outside of the defined range.
|
||||
* \returns false if value should be inserted into Octree.
|
||||
* \param filterValues are all read filter values in binary file.
|
||||
*/
|
||||
bool checkAllFilters(const std::vector<float>& filterValues);
|
||||
|
||||
/**
|
||||
* \returns true if star should be filtered away and false if all filters passed.
|
||||
* \param range contains ]min, max[ and \param filterValue corresponding value in
|
||||
* star. Star is filtered either if min = max = filterValue or if filterValue < min
|
||||
* (when min != 0.0) or filterValue > max (when max != 0.0).
|
||||
*/
|
||||
bool filterStar(const glm::vec2& range, float filterValue, float normValue = 0.f);
|
||||
|
||||
std::string _inFileOrFolderPath;
|
||||
std::string _outFileOrFolderPath;
|
||||
int _maxDist = 0;
|
||||
int _maxStarsPerNode = 0;
|
||||
bool _singleFileInput = false;
|
||||
|
||||
std::shared_ptr<OctreeManager> _octreeManager;
|
||||
std::shared_ptr<OctreeManager> _indexOctreeManager;
|
||||
|
||||
// Filter params
|
||||
glm::vec2 _posX = glm::vec2(0.f);
|
||||
bool _filterPosX = false;
|
||||
glm::vec2 _posY = glm::vec2(0.f);
|
||||
bool _filterPosY = false;
|
||||
glm::vec2 _posZ = glm::vec2(0.f);
|
||||
bool _filterPosZ = false;
|
||||
glm::vec2 _gMag = glm::vec2(0.f);
|
||||
bool _filterGMag = false;
|
||||
glm::vec2 _bpRp = glm::vec2(0.f);
|
||||
bool _filterBpRp = false;
|
||||
glm::vec2 _velX = glm::vec2(0.f);
|
||||
bool _filterVelX = false;
|
||||
glm::vec2 _velY = glm::vec2(0.f);
|
||||
bool _filterVelY = false;
|
||||
glm::vec2 _velZ = glm::vec2(0.f);
|
||||
bool _filterVelZ = false;
|
||||
glm::vec2 _bpMag = glm::vec2(0.f);
|
||||
bool _filterBpMag = false;
|
||||
glm::vec2 _rpMag = glm::vec2(0.f);
|
||||
bool _filterRpMag = false;
|
||||
glm::vec2 _bpG = glm::vec2(0.f);
|
||||
bool _filterBpG = false;
|
||||
glm::vec2 _gRp = glm::vec2(0.f);
|
||||
bool _filterGRp = false;
|
||||
glm::vec2 _ra = glm::vec2(0.f);
|
||||
bool _filterRa = false;
|
||||
glm::vec2 _raError = glm::vec2(0.f);
|
||||
bool _filterRaError = false;
|
||||
glm::vec2 _dec = glm::vec2(0.f);
|
||||
bool _filterDec = false;
|
||||
glm::vec2 _decError = glm::vec2(0.f);
|
||||
bool _filterDecError = false;
|
||||
glm::vec2 _parallax = glm::vec2(0.f);
|
||||
bool _filterParallax = false;
|
||||
glm::vec2 _parallaxError = glm::vec2(0.f);
|
||||
bool _filterParallaxError = false;
|
||||
glm::vec2 _pmra = glm::vec2(0.f);
|
||||
bool _filterPmra = false;
|
||||
glm::vec2 _pmraError = glm::vec2(0.f);
|
||||
bool _filterPmraError = false;
|
||||
glm::vec2 _pmdec = glm::vec2(0.f);
|
||||
bool _filterPmdec = false;
|
||||
glm::vec2 _pmdecError = glm::vec2(0.f);
|
||||
bool _filterPmdecError = false;
|
||||
glm::vec2 _rv = glm::vec2(0.f);
|
||||
bool _filterRv = false;
|
||||
glm::vec2 _rvError = glm::vec2(0.f);
|
||||
bool _filterRvError = false;
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
#endif // __OPENSPACE_MODULE_GAIA___CONSTRUCTOCTREETASK___H__
|
||||
@@ -1,102 +0,0 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2020 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
|
||||
* software and associated documentation files (the "Software"), to deal in the Software *
|
||||
* without restriction, including without limitation the rights to use, copy, modify, *
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
|
||||
* permit persons to whom the Software is furnished to do so, subject to the following *
|
||||
* conditions: *
|
||||
* *
|
||||
* The above copyright notice and this permission notice shall be included in all copies *
|
||||
* or substantial portions of the Software. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#include <modules/galaxy/tasks/milkywayconversiontask.h>
|
||||
|
||||
#include <modules/volume/textureslicevolumereader.h>
|
||||
#include <modules/volume/rawvolumewriter.h>
|
||||
#include <modules/volume/volumesampler.h>
|
||||
#include <modules/volume/textureslicevolumereader.h>
|
||||
|
||||
#include <modules/volume/rawvolumewriter.h>
|
||||
#include <openspace/documentation/documentation.h>
|
||||
|
||||
#include <ghoul/misc/dictionary.h>
|
||||
|
||||
namespace {
|
||||
constexpr const char* KeyInFilenamePrefix = "InFilenamePrefix";
|
||||
constexpr const char* KeyInFilenameSuffix = "InFilenameSuffix";
|
||||
constexpr const char* KeyInFirstIndex = "InFirstIndex";
|
||||
constexpr const char* KeyInNSlices = "InNSlices";
|
||||
constexpr const char* KeyOutFilename = "OutFilename";
|
||||
constexpr const char* KeyOutDimensions = "OutDimensions";
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
MilkywayConversionTask::MilkywayConversionTask(const ghoul::Dictionary& dictionary)
|
||||
: _inFirstIndex(0)
|
||||
, _inNSlices(0)
|
||||
{
|
||||
dictionary.getValue(KeyInFilenamePrefix, _inFilenamePrefix);
|
||||
dictionary.getValue(KeyInFilenameSuffix, _inFilenameSuffix);
|
||||
dictionary.getValue(KeyInFirstIndex, _inFirstIndex);
|
||||
dictionary.getValue(KeyInNSlices, _inNSlices);
|
||||
dictionary.getValue(KeyOutFilename, _outFilename);
|
||||
dictionary.getValue(KeyOutDimensions, _outDimensions);
|
||||
}
|
||||
|
||||
std::string MilkywayConversionTask::description() {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
void MilkywayConversionTask::perform(const Task::ProgressCallback& onProgress) {
|
||||
using namespace openspace::volume;
|
||||
|
||||
std::vector<std::string> filenames;
|
||||
for (size_t i = 0; i < _inNSlices; i++) {
|
||||
filenames.push_back(
|
||||
_inFilenamePrefix + std::to_string(i + _inFirstIndex) + _inFilenameSuffix
|
||||
);
|
||||
}
|
||||
|
||||
TextureSliceVolumeReader<glm::tvec4<GLfloat>> sliceReader(filenames, _inNSlices, 10);
|
||||
sliceReader.initialize();
|
||||
|
||||
RawVolumeWriter<glm::tvec4<GLfloat>> rawWriter(_outFilename);
|
||||
rawWriter.setDimensions(_outDimensions);
|
||||
|
||||
const glm::vec3 resolutionRatio = static_cast<glm::vec3>(sliceReader.dimensions()) /
|
||||
static_cast<glm::vec3>(rawWriter.dimensions());
|
||||
|
||||
VolumeSampler<TextureSliceVolumeReader<glm::tvec4<GLfloat>>> sampler(
|
||||
&sliceReader,
|
||||
resolutionRatio
|
||||
);
|
||||
std::function<glm::tvec4<GLfloat>(glm::ivec3)> sampleFunction =
|
||||
[&](glm::ivec3 outCoord) {
|
||||
const glm::vec3 inCoord = ((glm::vec3(outCoord) + glm::vec3(0.5f)) *
|
||||
resolutionRatio) - glm::vec3(0.5f);
|
||||
const glm::tvec4<GLfloat> value = sampler.sample(inCoord);
|
||||
return value;
|
||||
};
|
||||
|
||||
rawWriter.write(sampleFunction, onProgress);
|
||||
}
|
||||
|
||||
documentation::Documentation MilkywayConversionTask::documentation() {
|
||||
return documentation::Documentation();
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
@@ -0,0 +1,264 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2020 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
|
||||
* software and associated documentation files (the "Software"), to deal in the Software *
|
||||
* without restriction, including without limitation the rights to use, copy, modify, *
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
|
||||
* permit persons to whom the Software is furnished to do so, subject to the following *
|
||||
* conditions: *
|
||||
* *
|
||||
* The above copyright notice and this permission notice shall be included in all copies *
|
||||
* or substantial portions of the Software. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#include <modules/gaia/tasks/readfilejob.h>
|
||||
|
||||
#include <openspace/util/distanceconversion.h>
|
||||
#include <ghoul/misc/dictionary.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/fmt.h>
|
||||
|
||||
namespace {
|
||||
constexpr const char* _loggerCat = "ReadFileJob";
|
||||
}
|
||||
|
||||
namespace openspace::gaia {
|
||||
|
||||
ReadFileJob::ReadFileJob(std::string filePath, std::vector<std::string> allColumns,
|
||||
int firstRow, int lastRow, size_t nDefaultCols,
|
||||
int nValuesPerStar, std::shared_ptr<FitsFileReader> fitsReader)
|
||||
: _inFilePath(std::move(filePath))
|
||||
, _allColumns(std::move(allColumns))
|
||||
, _firstRow(firstRow)
|
||||
, _lastRow(lastRow)
|
||||
, _nDefaultCols(nDefaultCols)
|
||||
, _nValuesPerStar(nValuesPerStar)
|
||||
, _fitsFileReader(std::move(fitsReader))
|
||||
, _octants(8)
|
||||
{}
|
||||
|
||||
void ReadFileJob::execute() {
|
||||
// Read columns from FITS file. If rows aren't specified then full table will be read.
|
||||
std::shared_ptr<TableData<float>> table = _fitsFileReader->readTable<float>(
|
||||
_inFilePath,
|
||||
_allColumns,
|
||||
_firstRow,
|
||||
_lastRow
|
||||
);
|
||||
|
||||
if (!table) {
|
||||
throw ghoul::RuntimeError(
|
||||
fmt::format("Failed to open Fits file '{}'", _inFilePath
|
||||
));
|
||||
}
|
||||
|
||||
int nStars = table->readRows - _firstRow + 1;
|
||||
|
||||
int nNullArr = 0;
|
||||
size_t nColumnsRead = _allColumns.size();
|
||||
if (nColumnsRead != _nDefaultCols) {
|
||||
LINFO("Additional columns will be read! Consider add column in code for "
|
||||
"significant speedup!");
|
||||
}
|
||||
|
||||
// Copy columns to local variables.
|
||||
std::unordered_map<std::string, std::vector<float>>& tableContent = table->contents;
|
||||
|
||||
// Default columns parameters.
|
||||
//std::vector<float> l_longitude = std::move(tableContent[_allColumns[0]]);
|
||||
//std::vector<float> b_latitude = std::move(tableContent[_allColumns[1]]);
|
||||
std::vector<float> ra = std::move(tableContent[_allColumns[0]]);
|
||||
std::vector<float> ra_err = std::move(tableContent[_allColumns[1]]);
|
||||
std::vector<float> dec = std::move(tableContent[_allColumns[2]]);
|
||||
std::vector<float> dec_err = std::move(tableContent[_allColumns[3]]);
|
||||
std::vector<float> parallax = std::move(tableContent[_allColumns[4]]);
|
||||
std::vector<float> parallax_err = std::move(tableContent[_allColumns[5]]);
|
||||
std::vector<float> pmra = std::move(tableContent[_allColumns[6]]);
|
||||
std::vector<float> pmra_err = std::move(tableContent[_allColumns[7]]);
|
||||
std::vector<float> pmdec = std::move(tableContent[_allColumns[8]]);
|
||||
std::vector<float> pmdec_err = std::move(tableContent[_allColumns[9]]);
|
||||
std::vector<float> meanMagG = std::move(tableContent[_allColumns[10]]);
|
||||
std::vector<float> meanMagBp = std::move(tableContent[_allColumns[11]]);
|
||||
std::vector<float> meanMagRp = std::move(tableContent[_allColumns[12]]);
|
||||
std::vector<float> bp_rp = std::move(tableContent[_allColumns[13]]);
|
||||
std::vector<float> bp_g = std::move(tableContent[_allColumns[14]]);
|
||||
std::vector<float> g_rp = std::move(tableContent[_allColumns[15]]);
|
||||
std::vector<float> radial_vel = std::move(tableContent[_allColumns[16]]);
|
||||
std::vector<float> radial_vel_err = std::move(tableContent[_allColumns[17]]);
|
||||
|
||||
|
||||
// Construct data array. OBS: ORDERING IS IMPORTANT! This is where slicing happens.
|
||||
for (int i = 0; i < nStars; ++i) {
|
||||
std::vector<float> values(_nValuesPerStar);
|
||||
size_t idx = 0;
|
||||
|
||||
// Default order for rendering:
|
||||
// Position [X, Y, Z]
|
||||
// Mean G-band Magnitude
|
||||
// -- Mean Bp-band Magnitude
|
||||
// -- Mean Rp-band Magnitude
|
||||
// Bp-Rp Color
|
||||
// -- Bp-G Color
|
||||
// -- G-Rp Color
|
||||
// Velocity [X, Y, Z]
|
||||
|
||||
// Return early if star doesn't have a measured position.
|
||||
if (std::isnan(ra[i]) || std::isnan(dec[i])) {
|
||||
nNullArr++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Store positions. Set to a default distance if parallax doesn't exist.
|
||||
float radiusInKiloParsec = 9.0;
|
||||
if (!std::isnan(parallax[i])) {
|
||||
// Parallax is in milliArcseconds -> distance in kiloParsecs
|
||||
// https://gea.esac.esa.int/archive/documentation/GDR2/Gaia_archive/
|
||||
// chap_datamodel/sec_dm_main_tables/ssec_dm_gaia_source.html
|
||||
//LINFO("Parallax: " + std::to_string(parallax[i]));
|
||||
radiusInKiloParsec = 1.f / parallax[i];
|
||||
}
|
||||
/*// Convert to Galactic Coordinates from Galactic Lon & Lat.
|
||||
// https://gea.esac.esa.int/archive/documentation/GDR2/Data_processing/
|
||||
// chap_cu3ast/sec_cu3ast_intro/ssec_cu3ast_intro_tansforms.html#SSS1
|
||||
values[idx++] = radiusInKiloParsec * cos(glm::radians(b_latitude[i])) *
|
||||
cos(glm::radians(l_longitude[i])); // Pos X
|
||||
values[idx++] = radiusInKiloParsec * cos(glm::radians(b_latitude[i])) *
|
||||
sin(glm::radians(l_longitude[i])); // Pos Y
|
||||
values[idx++] = radiusInKiloParsec * sin(glm::radians(b_latitude[i])); // Pos Z
|
||||
*/
|
||||
|
||||
// Convert ICRS Equatorial Ra and Dec to Galactic latitude and longitude.
|
||||
glm::mat3 aPrimG = glm::mat3(
|
||||
// Col 0
|
||||
glm::vec3(-0.0548755604162154, 0.4941094278755837, -0.8676661490190047),
|
||||
// Col 1
|
||||
glm::vec3(-0.8734370902348850, -0.4448296299600112, -0.1980763734312015),
|
||||
// Col 2
|
||||
glm::vec3(-0.4838350155487132, 0.7469822444972189, 0.4559837761750669)
|
||||
);
|
||||
glm::vec3 rICRS = glm::vec3(
|
||||
cos(glm::radians(ra[i])) * cos(glm::radians(dec[i])),
|
||||
sin(glm::radians(ra[i])) * cos(glm::radians(dec[i])),
|
||||
sin(glm::radians(dec[i]))
|
||||
);
|
||||
glm::vec3 rGal = aPrimG * rICRS;
|
||||
values[idx++] = radiusInKiloParsec * rGal.x; // Pos X
|
||||
values[idx++] = radiusInKiloParsec * rGal.y; // Pos Y
|
||||
values[idx++] = radiusInKiloParsec * rGal.z; // Pos Z
|
||||
|
||||
/*if (abs(rGal.x - values[0]) > 1e-5 || abs(rGal.y - values[1]) > 1e-5 ||
|
||||
abs(rGal.z - values[2]) > 1e-5) {
|
||||
LINFO("rGal: " + std::to_string(rGal) +
|
||||
" - LB: [" + std::to_string(values[0]) + ", " + std::to_string(values[1]) +
|
||||
", " + std::to_string(values[2]) + "]");
|
||||
}*/
|
||||
|
||||
// Store magnitude render value. (Set default to high mag = low brightness)
|
||||
values[idx++] = std::isnan(meanMagG[i]) ? 20.f : meanMagG[i]; // Mean G-band Mag
|
||||
|
||||
// Store color render value. (Default value is bluish stars)
|
||||
values[idx++] = std::isnan(bp_rp[i]) ? 0.f : bp_rp[i]; // Bp-Rp Color
|
||||
|
||||
|
||||
// Store velocity.
|
||||
if (std::isnan(pmra[i])) {
|
||||
pmra[i] = 0.f;
|
||||
}
|
||||
if (std::isnan(pmdec[i])) {
|
||||
pmdec[i] = 0.f;
|
||||
}
|
||||
|
||||
// Convert Proper Motion from ICRS [Ra,Dec] to Galactic Tanget Vector [l,b].
|
||||
glm::vec3 uICRS = glm::vec3(
|
||||
-sin(glm::radians(ra[i])) * pmra[i] -
|
||||
cos(glm::radians(ra[i])) * sin(glm::radians(dec[i])) * pmdec[i],
|
||||
cos(glm::radians(ra[i])) * pmra[i] -
|
||||
sin(glm::radians(ra[i])) * sin(glm::radians(dec[i])) * pmdec[i],
|
||||
cos(glm::radians(dec[i])) * pmdec[i]
|
||||
);
|
||||
glm::vec3 pmVecGal = aPrimG * uICRS;
|
||||
|
||||
// Convert to Tangential vector [m/s] from Proper Motion vector [mas/yr]
|
||||
float tanVelX = 1000.f * 4.74f * radiusInKiloParsec * pmVecGal.x;
|
||||
float tanVelY = 1000.f * 4.74f * radiusInKiloParsec * pmVecGal.y;
|
||||
float tanVelZ = 1000.f * 4.74f * radiusInKiloParsec * pmVecGal.z;
|
||||
|
||||
// Calculate True Space Velocity [m/s] if we have the radial velocity
|
||||
if (!std::isnan(radial_vel[i])) {
|
||||
// Calculate Radial Velocity in the direction of the star.
|
||||
// radial_vel is given in [km/s] -> convert to [m/s].
|
||||
float radVelX = 1000.f * radial_vel[i] * rGal.x;
|
||||
float radVelY = 1000.f * radial_vel[i] * rGal.y;
|
||||
float radVelZ = 1000.f * radial_vel[i] * rGal.z;
|
||||
|
||||
// Use Pythagoras theorem for the final Space Velocity [m/s].
|
||||
values[idx++] = sqrt(pow(radVelX, 2) + pow(tanVelX, 2)); // Vel X [U]
|
||||
values[idx++] = sqrt(pow(radVelY, 2) + pow(tanVelY, 2)); // Vel Y [V]
|
||||
values[idx++] = sqrt(pow(radVelZ, 2) + pow(tanVelZ, 2)); // Vel Z [W]
|
||||
}
|
||||
// Otherwise use the vector [m/s] we got from proper motion.
|
||||
else {
|
||||
radial_vel[i] = 0.f;
|
||||
values[idx++] = tanVelX; // Vel X [U]
|
||||
values[idx++] = tanVelY; // Vel Y [V]
|
||||
values[idx++] = tanVelZ; // Vel Z [W]
|
||||
}
|
||||
|
||||
// Store additional parameters to filter by.
|
||||
values[idx++] = std::isnan(meanMagBp[i]) ? 20.f : meanMagBp[i];
|
||||
values[idx++] = std::isnan(meanMagRp[i]) ? 20.f : meanMagRp[i];
|
||||
values[idx++] = std::isnan(bp_g[i]) ? 0.f : bp_g[i];
|
||||
values[idx++] = std::isnan(g_rp[i]) ? 0.f : g_rp[i];
|
||||
values[idx++] = ra[i];
|
||||
values[idx++] = std::isnan(ra_err[i]) ? 0.f : ra_err[i];
|
||||
values[idx++] = dec[i];
|
||||
values[idx++] = std::isnan(dec_err[i]) ? 0.f : dec_err[i];
|
||||
values[idx++] = std::isnan(parallax[i]) ? 0.f : parallax[i];
|
||||
values[idx++] = std::isnan(parallax_err[i]) ? 0.f : parallax_err[i];
|
||||
values[idx++] = pmra[i];
|
||||
values[idx++] = std::isnan(pmra_err[i]) ? 0.f : pmra_err[i];
|
||||
values[idx++] = pmdec[i];
|
||||
values[idx++] = std::isnan(pmdec_err[i]) ? 0.f : pmdec_err[i];
|
||||
values[idx++] = radial_vel[i];
|
||||
values[idx++] = std::isnan(radial_vel_err[i]) ? 0.f : radial_vel_err[i];
|
||||
|
||||
// Read extra columns, if any. This will slow down the sorting tremendously!
|
||||
for (size_t col = _nDefaultCols; col < nColumnsRead; ++col) {
|
||||
std::vector<float> vecData = std::move(tableContent[_allColumns[col]]);
|
||||
values[idx++] = std::isnan(vecData[col]) ? 0.f : vecData[col];
|
||||
}
|
||||
|
||||
size_t index = 0;
|
||||
if (values[0] < 0.0) {
|
||||
index += 1;
|
||||
}
|
||||
if (values[1] < 0.0) {
|
||||
index += 2;
|
||||
}
|
||||
if (values[2] < 0.0) {
|
||||
index += 4;
|
||||
}
|
||||
|
||||
_octants[index].insert(_octants[index].end(), values.begin(), values.end());
|
||||
}
|
||||
|
||||
/*LINFO(std::to_string(nNullArr) + " out of " +
|
||||
std::to_string(nStars) + " read stars were nullArrays.");*/
|
||||
}
|
||||
|
||||
std::vector<std::vector<float>> ReadFileJob::product() {
|
||||
return _octants;
|
||||
}
|
||||
|
||||
} // namespace openspace::gaiamission
|
||||
@@ -0,0 +1,71 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2020 *
|
||||
* *
|
||||
* 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_MODULE_GAIA___READFILEJOB___H__
|
||||
#define __OPENSPACE_MODULE_GAIA___READFILEJOB___H__
|
||||
|
||||
#include <openspace/util/concurrentjobmanager.h>
|
||||
|
||||
#include <modules/fitsfilereader/include/fitsfilereader.h>
|
||||
|
||||
namespace openspace::gaia {
|
||||
|
||||
struct ReadFileJob : public Job<std::vector<std::vector<float>>> {
|
||||
/**
|
||||
* Constructs a Job that will read a single FITS file in a concurrent thread and
|
||||
* divide the star data into 8 octants depending on position.
|
||||
* \param allColumns define which columns that will be read, it should correspond
|
||||
* to the pre-defined order in the job. If additional columns are defined they will
|
||||
* be read but slow down the process.
|
||||
* Proper conversions of positions and velocities will take place and all values
|
||||
* will be checked for NaNs.
|
||||
* If \param firstRow is < 1 then reading will begin at first row in table.
|
||||
* If \param lastRow < firstRow then entire table will be read.
|
||||
* \param nValuesPerStar defines how many values that will be stored per star.
|
||||
*/
|
||||
ReadFileJob(std::string filePath, std::vector<std::string> allColumns, int firstRow,
|
||||
int lastRow, size_t nDefaultCols, int nValuesPerStar,
|
||||
std::shared_ptr<FitsFileReader> fitsReader);
|
||||
|
||||
~ReadFileJob() = default;
|
||||
|
||||
void execute() override;
|
||||
|
||||
std::vector<std::vector<float>> product() override;
|
||||
|
||||
private:
|
||||
std::string _inFilePath;
|
||||
int _firstRow;
|
||||
int _lastRow;
|
||||
size_t _nDefaultCols;
|
||||
int _nValuesPerStar;
|
||||
std::vector<std::string> _allColumns;
|
||||
|
||||
std::shared_ptr<FitsFileReader> _fitsFileReader;
|
||||
std::vector<std::vector<float>> _octants;
|
||||
};
|
||||
|
||||
} // namespace openspace::gaiamission
|
||||
|
||||
#endif // __OPENSPACE_MODULE_GAIA___READFILEJOB___H__
|
||||
@@ -0,0 +1,392 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2020 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
|
||||
* software and associated documentation files (the "Software"), to deal in the Software *
|
||||
* without restriction, including without limitation the rights to use, copy, modify, *
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
|
||||
* permit persons to whom the Software is furnished to do so, subject to the following *
|
||||
* conditions: *
|
||||
* *
|
||||
* The above copyright notice and this permission notice shall be included in all copies *
|
||||
* or substantial portions of the Software. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#include <modules/gaia/tasks/readfitstask.h>
|
||||
|
||||
#include <modules/gaia/tasks/readfilejob.h>
|
||||
#include <openspace/documentation/documentation.h>
|
||||
#include <openspace/documentation/verifier.h>
|
||||
|
||||
#include <ghoul/misc/dictionary.h>
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <ghoul/filesystem/directory.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/fmt.h>
|
||||
|
||||
#include <fstream>
|
||||
#include <set>
|
||||
|
||||
namespace {
|
||||
constexpr const char* KeyInFileOrFolderPath = "InFileOrFolderPath";
|
||||
constexpr const char* KeyOutFileOrFolderPath = "OutFileOrFolderPath";
|
||||
constexpr const char* KeySingleFileProcess = "SingleFileProcess";
|
||||
constexpr const char* KeyThreadsToUse = "ThreadsToUse";
|
||||
constexpr const char* KeyFirstRow = "FirstRow";
|
||||
constexpr const char* KeyLastRow = "LastRow";
|
||||
constexpr const char* KeyFilterColumnNames = "FilterColumnNames";
|
||||
|
||||
constexpr const char* _loggerCat = "ReadFitsTask";
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
ReadFitsTask::ReadFitsTask(const ghoul::Dictionary& dictionary) {
|
||||
openspace::documentation::testSpecificationAndThrow(
|
||||
documentation(),
|
||||
dictionary,
|
||||
"ReadFitsTask"
|
||||
);
|
||||
|
||||
_inFileOrFolderPath = absPath(dictionary.value<std::string>(KeyInFileOrFolderPath));
|
||||
_outFileOrFolderPath = absPath(dictionary.value<std::string>(KeyOutFileOrFolderPath));
|
||||
|
||||
if (dictionary.hasKey(KeySingleFileProcess)) {
|
||||
_singleFileProcess = dictionary.value<bool>(KeySingleFileProcess);
|
||||
}
|
||||
|
||||
if (dictionary.hasKey(KeyThreadsToUse)) {
|
||||
_threadsToUse = static_cast<size_t>(dictionary.value<double>(KeyThreadsToUse));
|
||||
if (_threadsToUse < 1) {
|
||||
LINFO(fmt::format(
|
||||
"User defined ThreadsToUse was: {}. Will be set to 1", _threadsToUse
|
||||
));
|
||||
_threadsToUse = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (dictionary.hasKey(KeyFirstRow)) {
|
||||
_firstRow = static_cast<int>(dictionary.value<double>(KeyFirstRow));
|
||||
}
|
||||
|
||||
if (dictionary.hasKey(KeyLastRow)) {
|
||||
_lastRow = static_cast<int>(dictionary.value<double>(KeyLastRow));
|
||||
}
|
||||
|
||||
|
||||
if (dictionary.hasKey(KeyFilterColumnNames)) {
|
||||
ghoul::Dictionary d = dictionary.value<ghoul::Dictionary>(KeyFilterColumnNames);
|
||||
|
||||
// Ugly fix for ASCII sorting when there are more columns read than 10.
|
||||
std::set<int> intKeys;
|
||||
for (const std::string& key : d.keys()) {
|
||||
intKeys.insert(std::stoi(key));
|
||||
}
|
||||
|
||||
for (int key : intKeys) {
|
||||
_filterColumnNames.push_back(d.value<std::string>(std::to_string(key)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string ReadFitsTask::description() {
|
||||
return fmt::format(
|
||||
"Read the specified fits file (or all fits files in specified folder): {}\n and "
|
||||
"write raw star data into: {}\nAll columns required for default rendering and "
|
||||
"filtering parameters will always be read but user can define additional filter "
|
||||
"columns to read.", _inFileOrFolderPath, _outFileOrFolderPath
|
||||
);
|
||||
}
|
||||
|
||||
void ReadFitsTask::perform(const Task::ProgressCallback& onProgress) {
|
||||
onProgress(0.f);
|
||||
|
||||
if (_singleFileProcess) {
|
||||
readSingleFitsFile(onProgress);
|
||||
}
|
||||
else {
|
||||
readAllFitsFilesFromFolder(onProgress);
|
||||
}
|
||||
|
||||
onProgress(1.f);
|
||||
}
|
||||
|
||||
void ReadFitsTask::readSingleFitsFile(const Task::ProgressCallback& progressCallback) {
|
||||
int32_t nValuesPerStar = 0;
|
||||
|
||||
FitsFileReader fileReader(false);
|
||||
std::vector<float> fullData = fileReader.readFitsFile(
|
||||
_inFileOrFolderPath,
|
||||
nValuesPerStar,
|
||||
_firstRow,
|
||||
_lastRow,
|
||||
_filterColumnNames
|
||||
);
|
||||
|
||||
progressCallback(0.8f);
|
||||
|
||||
std::ofstream outFileStream(_outFileOrFolderPath, std::ofstream::binary);
|
||||
if (outFileStream.good()) {
|
||||
int32_t nValues = static_cast<int32_t>(fullData.size());
|
||||
LINFO(fmt::format("Writing {} values to file {}", nValues, _outFileOrFolderPath));
|
||||
LINFO("Number of values per star: " + std::to_string(nValuesPerStar));
|
||||
|
||||
if (nValues == 0) {
|
||||
LERROR("Error writing file - No values were read from file.");
|
||||
}
|
||||
outFileStream.write(
|
||||
reinterpret_cast<const char*>(&nValues),
|
||||
sizeof(int32_t)
|
||||
);
|
||||
outFileStream.write(
|
||||
reinterpret_cast<const char*>(&nValuesPerStar),
|
||||
sizeof(int32_t)
|
||||
);
|
||||
|
||||
size_t nBytes = nValues * sizeof(fullData[0]);
|
||||
outFileStream.write(reinterpret_cast<const char*>(fullData.data()), nBytes);
|
||||
|
||||
outFileStream.close();
|
||||
}
|
||||
else {
|
||||
LERROR(fmt::format(
|
||||
"Error opening file: {} as output data file.", _outFileOrFolderPath
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
void ReadFitsTask::readAllFitsFilesFromFolder(const Task::ProgressCallback&) {
|
||||
std::vector<std::vector<float>> octants(8);
|
||||
std::vector<bool> isFirstWrite(8, true);
|
||||
size_t finishedJobs = 0;
|
||||
int totalStars = 0;
|
||||
|
||||
_firstRow = std::max(_firstRow, 1);
|
||||
|
||||
// Create Threadpool and JobManager.
|
||||
LINFO("Threads in pool: " + std::to_string(_threadsToUse));
|
||||
ThreadPool threadPool(_threadsToUse);
|
||||
ConcurrentJobManager<std::vector<std::vector<float>>> jobManager(threadPool);
|
||||
|
||||
// Get all files in specified folder.
|
||||
ghoul::filesystem::Directory currentDir(_inFileOrFolderPath);
|
||||
std::vector<std::string> allInputFiles = currentDir.readFiles();
|
||||
size_t nInputFiles = allInputFiles.size();
|
||||
LINFO("Files to read: " + std::to_string(nInputFiles));
|
||||
|
||||
// Define what columns to read.
|
||||
_allColumnNames.clear();
|
||||
// Read in the order of table in file.
|
||||
std::vector<std::string> defaultColumnNames = {
|
||||
"ra",
|
||||
"ra_error",
|
||||
"dec",
|
||||
"dec_error",
|
||||
"parallax",
|
||||
"parallax_error",
|
||||
"pmra",
|
||||
"pmra_error",
|
||||
"pmdec",
|
||||
"pmdec_error",
|
||||
"phot_g_mean_mag",
|
||||
"phot_bp_mean_mag",
|
||||
"phot_rp_mean_mag",
|
||||
"bp_rp",
|
||||
"bp_g",
|
||||
"g_rp",
|
||||
"radial_velocity",
|
||||
"radial_velocity_error",
|
||||
};
|
||||
_allColumnNames.insert(
|
||||
_allColumnNames.end(),
|
||||
defaultColumnNames.begin(),
|
||||
defaultColumnNames.end()
|
||||
);
|
||||
// Append additional filter parameters to default rendering parameters.
|
||||
_allColumnNames.insert(
|
||||
_allColumnNames.end(),
|
||||
_filterColumnNames.begin(),
|
||||
_filterColumnNames.end()
|
||||
);
|
||||
|
||||
std::string allNames = "Columns to read: \n";
|
||||
for (const std::string& colName : _allColumnNames) {
|
||||
allNames += colName + "\n";
|
||||
}
|
||||
LINFO(allNames);
|
||||
|
||||
// Declare how many values to save for each star.
|
||||
int32_t nValuesPerStar = 24;
|
||||
size_t nDefaultColumns = defaultColumnNames.size();
|
||||
auto fitsFileReader = std::make_shared<FitsFileReader>(false);
|
||||
|
||||
// Divide all files into ReadFilejobs and then delegate them onto several threads!
|
||||
while (!allInputFiles.empty()) {
|
||||
std::string fileToRead = allInputFiles.back();
|
||||
allInputFiles.erase(allInputFiles.end() - 1);
|
||||
|
||||
// Add reading of file to jobmanager, which will distribute it to our threadpool.
|
||||
auto readFileJob = std::make_shared<gaia::ReadFileJob>(
|
||||
fileToRead,
|
||||
_allColumnNames,
|
||||
_firstRow,
|
||||
_lastRow,
|
||||
nDefaultColumns,
|
||||
nValuesPerStar,
|
||||
fitsFileReader
|
||||
);
|
||||
jobManager.enqueueJob(readFileJob);
|
||||
}
|
||||
|
||||
LINFO("All files added to queue!");
|
||||
|
||||
// Check for finished jobs.
|
||||
while (finishedJobs < nInputFiles) {
|
||||
if (jobManager.numFinishedJobs() > 0) {
|
||||
std::vector<std::vector<float>> newOctant =
|
||||
jobManager.popFinishedJob()->product();
|
||||
|
||||
finishedJobs++;
|
||||
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
// Add read values to global octant and check if it's time to write!
|
||||
octants[i].insert(
|
||||
octants[i].end(),
|
||||
newOctant[i].begin(),
|
||||
newOctant[i].end()
|
||||
);
|
||||
if ((octants[i].size() > MAX_SIZE_BEFORE_WRITE) ||
|
||||
(finishedJobs == nInputFiles))
|
||||
{
|
||||
// Write to file!
|
||||
totalStars += writeOctantToFile(
|
||||
octants[i],
|
||||
i,
|
||||
isFirstWrite,
|
||||
nValuesPerStar
|
||||
);
|
||||
|
||||
octants[i].clear();
|
||||
octants[i].shrink_to_fit();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
LINFO(fmt::format("A total of {} stars were written to binary files.", totalStars));
|
||||
}
|
||||
|
||||
int ReadFitsTask::writeOctantToFile(const std::vector<float>& octantData, int index,
|
||||
std::vector<bool>& isFirstWrite, int nValuesPerStar)
|
||||
{
|
||||
std::string outPath = fmt::format("{}octant_{}.bin", _outFileOrFolderPath, index);
|
||||
std::ofstream fileStream(outPath, std::ofstream::binary | std::ofstream::app);
|
||||
if (fileStream.good()) {
|
||||
int32_t nValues = static_cast<int32_t>(octantData.size());
|
||||
LINFO("Write " + std::to_string(nValues) + " values to " + outPath);
|
||||
|
||||
if (nValues == 0) {
|
||||
LERROR("Error writing file - No values were read from file.");
|
||||
}
|
||||
// If this is the first write then write number of values per star!
|
||||
if (isFirstWrite[index]) {
|
||||
LINFO("First write for Octant_" + std::to_string(index));
|
||||
fileStream.write(
|
||||
reinterpret_cast<const char*>(&nValuesPerStar),
|
||||
sizeof(int32_t)
|
||||
);
|
||||
isFirstWrite[index] = false;
|
||||
}
|
||||
|
||||
size_t nBytes = nValues * sizeof(octantData[0]);
|
||||
fileStream.write(reinterpret_cast<const char*>(octantData.data()), nBytes);
|
||||
|
||||
fileStream.close();
|
||||
|
||||
// Return number of stars written.
|
||||
return nValues / nValuesPerStar;
|
||||
}
|
||||
else {
|
||||
LERROR(fmt::format("Error opening file: {} as output data file.", outPath));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
documentation::Documentation ReadFitsTask::Documentation() {
|
||||
using namespace documentation;
|
||||
return {
|
||||
"ReadFitsFile",
|
||||
"gaiamission_fitsfiletorawdata",
|
||||
{
|
||||
{
|
||||
"Type",
|
||||
new StringEqualVerifier("ReadFitsTask"),
|
||||
Optional::No
|
||||
},
|
||||
{
|
||||
KeyInFileOrFolderPath,
|
||||
new StringVerifier,
|
||||
Optional::No,
|
||||
"If SingleFileProcess is set to true then this specifies the path to a "
|
||||
"single FITS file that will be read. Otherwise it specifies the path to "
|
||||
"a folder with multiple FITS files that are to be read.",
|
||||
},
|
||||
{
|
||||
KeyOutFileOrFolderPath,
|
||||
new StringVerifier,
|
||||
Optional::No,
|
||||
"If SingleFileProcess is set to true then this specifies the name "
|
||||
"(including entire path) to the output file. Otherwise it specifies the "
|
||||
"path to the output folder which to export binary star data to.",
|
||||
},
|
||||
{
|
||||
KeySingleFileProcess,
|
||||
new BoolVerifier,
|
||||
Optional::Yes,
|
||||
"If true then task will read from a single FITS file and output a single "
|
||||
"binary file. If false then task will read all files in specified folder "
|
||||
"and output multiple files sorted by location."
|
||||
},
|
||||
{
|
||||
KeyThreadsToUse,
|
||||
new IntVerifier,
|
||||
Optional::Yes,
|
||||
"Defines how many threads to use when reading from multiple files."
|
||||
},
|
||||
{
|
||||
KeyFirstRow,
|
||||
new IntVerifier,
|
||||
Optional::Yes,
|
||||
"Defines the first row that will be read from the specified FITS "
|
||||
"file(s). If not defined then reading will start at first row.",
|
||||
},
|
||||
{
|
||||
KeyLastRow,
|
||||
new IntVerifier,
|
||||
Optional::Yes,
|
||||
"Defines the last row that will be read from the specified FITS file(s). "
|
||||
"If not defined (or less than FirstRow) then full file(s) will be read.",
|
||||
},
|
||||
{
|
||||
KeyFilterColumnNames,
|
||||
new StringListVerifier,
|
||||
Optional::Yes,
|
||||
"A list of strings with the names of all the additional columns that are "
|
||||
"to be read from the specified FITS file(s). These columns can be used "
|
||||
"for filtering while constructing Octree later.",
|
||||
},
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
@@ -0,0 +1,82 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2020 *
|
||||
* *
|
||||
* 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_MODULE_GAIA___READFITSTASK___H__
|
||||
#define __OPENSPACE_MODULE_GAIA___READFITSTASK___H__
|
||||
|
||||
#include <openspace/util/task.h>
|
||||
#include <openspace/util/threadpool.h>
|
||||
#include <openspace/util/concurrentjobmanager.h>
|
||||
#include <modules/fitsfilereader/include/fitsfilereader.h>
|
||||
|
||||
namespace openspace {
|
||||
|
||||
namespace documentation { struct Documentation; }
|
||||
|
||||
class ReadFitsTask : public Task {
|
||||
public:
|
||||
ReadFitsTask(const ghoul::Dictionary& dictionary);
|
||||
virtual ~ReadFitsTask() = default;
|
||||
|
||||
std::string description() override;
|
||||
void perform(const Task::ProgressCallback& onProgress) override;
|
||||
static documentation::Documentation Documentation();
|
||||
|
||||
private:
|
||||
const size_t MAX_SIZE_BEFORE_WRITE = 48000000; // ~183MB -> 2M stars with 24 values
|
||||
//const size_t MAX_SIZE_BEFORE_WRITE = 9000000; // ~34MB -> 0,5 stars with 18 values
|
||||
|
||||
/**
|
||||
* Reads a single FITS file and stores ordered star data in one binary file.
|
||||
*/
|
||||
void readSingleFitsFile(const Task::ProgressCallback& progressCallback);
|
||||
|
||||
/**
|
||||
* Reads all FITS files in a folder with multiple threads and stores ordered star
|
||||
* data into 8 binary files.
|
||||
*/
|
||||
void readAllFitsFilesFromFolder(const Task::ProgressCallback& progressCallback);
|
||||
|
||||
/**
|
||||
* Writes \param data to octant [\param index] file.
|
||||
* \param isFirstWrite defines if this is the first write to specified octant, if so
|
||||
* the file is created, otherwise the accumulated data is appended to the end of the
|
||||
* file.
|
||||
*/
|
||||
int writeOctantToFile(const std::vector<float>& data, int index,
|
||||
std::vector<bool>& isFirstWrite, int nValuesPerStar);
|
||||
|
||||
std::string _inFileOrFolderPath;
|
||||
std::string _outFileOrFolderPath;
|
||||
bool _singleFileProcess = false;
|
||||
size_t _threadsToUse = 1;
|
||||
int _firstRow = 0;
|
||||
int _lastRow = 0;
|
||||
std::vector<std::string> _allColumnNames;
|
||||
std::vector<std::string> _filterColumnNames;
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
#endif // __OPENSPACE_MODULE_GAIA___READFITSTASK___H__
|
||||
@@ -0,0 +1,122 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2020 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
|
||||
* software and associated documentation files (the "Software"), to deal in the Software *
|
||||
* without restriction, including without limitation the rights to use, copy, modify, *
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
|
||||
* permit persons to whom the Software is furnished to do so, subject to the following *
|
||||
* conditions: *
|
||||
* *
|
||||
* The above copyright notice and this permission notice shall be included in all copies *
|
||||
* or substantial portions of the Software. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#include <modules/gaia/tasks/readspecktask.h>
|
||||
|
||||
#include <modules/fitsfilereader/include/fitsfilereader.h>
|
||||
#include <openspace/documentation/documentation.h>
|
||||
#include <openspace/documentation/verifier.h>
|
||||
#include <ghoul/fmt.h>
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/misc/dictionary.h>
|
||||
#include <fstream>
|
||||
|
||||
namespace {
|
||||
constexpr const char* KeyInFilePath = "InFilePath";
|
||||
constexpr const char* KeyOutFilePath = "OutFilePath";
|
||||
|
||||
constexpr const char* _loggerCat = "ReadSpeckTask";
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
ReadSpeckTask::ReadSpeckTask(const ghoul::Dictionary& dictionary) {
|
||||
openspace::documentation::testSpecificationAndThrow(
|
||||
documentation(),
|
||||
dictionary,
|
||||
"ReadSpeckTask"
|
||||
);
|
||||
|
||||
_inFilePath = absPath(dictionary.value<std::string>(KeyInFilePath));
|
||||
_outFilePath = absPath(dictionary.value<std::string>(KeyOutFilePath));
|
||||
}
|
||||
|
||||
std::string ReadSpeckTask::description() {
|
||||
return fmt::format(
|
||||
"Read speck file {} and write raw star data into {}", _inFilePath, _outFilePath
|
||||
);
|
||||
}
|
||||
|
||||
void ReadSpeckTask::perform(const Task::ProgressCallback& onProgress) {
|
||||
onProgress(0.f);
|
||||
|
||||
int32_t nRenderValues = 0;
|
||||
|
||||
FitsFileReader fileReader(false);
|
||||
std::vector<float> fullData = fileReader.readSpeckFile(_inFilePath, nRenderValues);
|
||||
|
||||
onProgress(0.9f);
|
||||
|
||||
std::ofstream fileStream(_outFilePath, std::ofstream::binary);
|
||||
if (fileStream.good()) {
|
||||
int32_t nValues = static_cast<int32_t>(fullData.size());
|
||||
LINFO("nValues: " + std::to_string(nValues));
|
||||
|
||||
if (nValues == 0) {
|
||||
LERROR("Error writing file - No values were read from file.");
|
||||
}
|
||||
fileStream.write(reinterpret_cast<const char*>(&nValues), sizeof(int32_t));
|
||||
fileStream.write(reinterpret_cast<const char*>(&nRenderValues), sizeof(int32_t));
|
||||
|
||||
size_t nBytes = nValues * sizeof(fullData[0]);
|
||||
fileStream.write(reinterpret_cast<const char*>(fullData.data()), nBytes);
|
||||
|
||||
fileStream.close();
|
||||
}
|
||||
else {
|
||||
LERROR(fmt::format("Error opening file: {} as output data file.", _outFilePath));
|
||||
}
|
||||
|
||||
onProgress(1.f);
|
||||
}
|
||||
|
||||
documentation::Documentation ReadSpeckTask::Documentation() {
|
||||
using namespace documentation;
|
||||
return {
|
||||
"ReadSpeckTask",
|
||||
"gaiamission_speckfiletorawdata",
|
||||
{
|
||||
{
|
||||
"Type",
|
||||
new StringEqualVerifier("ReadSpeckTask"),
|
||||
Optional::No
|
||||
},
|
||||
{
|
||||
KeyInFilePath,
|
||||
new StringVerifier,
|
||||
Optional::No,
|
||||
"The path to the SPECK file that are to be read.",
|
||||
},
|
||||
{
|
||||
KeyOutFilePath,
|
||||
new StringVerifier,
|
||||
Optional::No,
|
||||
"The path to the file to export raw VBO data to.",
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
+10
-19
@@ -22,40 +22,31 @@
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#ifndef __OPENSPACE_MODULE_GALAXY___MILKYWAYCONVERSIONTASK___H__
|
||||
#define __OPENSPACE_MODULE_GALAXY___MILKYWAYCONVERSIONTASK___H__
|
||||
#ifndef __OPENSPACE_MODULE_GAIA___READSPECKTASK___H__
|
||||
#define __OPENSPACE_MODULE_GAIA___READSPECKTASK___H__
|
||||
|
||||
#include <openspace/util/task.h>
|
||||
|
||||
#include <ghoul/glm.h>
|
||||
#include <string>
|
||||
|
||||
namespace openspace {
|
||||
|
||||
namespace documentation { struct Documentation; }
|
||||
|
||||
/**
|
||||
* Converts a set of exr image slices to a raw volume
|
||||
* with floating point RGBA data (32 bit per channel).
|
||||
*/
|
||||
class MilkywayConversionTask : public Task {
|
||||
class ReadSpeckTask : public Task {
|
||||
public:
|
||||
MilkywayConversionTask(const ghoul::Dictionary& dictionary);
|
||||
virtual ~MilkywayConversionTask() = default;
|
||||
ReadSpeckTask(const ghoul::Dictionary& dictionary);
|
||||
virtual ~ReadSpeckTask() = default;
|
||||
|
||||
std::string description() override;
|
||||
void perform(const Task::ProgressCallback& onProgress) override;
|
||||
|
||||
static documentation::Documentation documentation();
|
||||
static documentation::Documentation Documentation();
|
||||
|
||||
private:
|
||||
std::string _inFilenamePrefix;
|
||||
std::string _inFilenameSuffix;
|
||||
size_t _inFirstIndex = 0;
|
||||
size_t _inNSlices = 0;
|
||||
std::string _outFilename;
|
||||
glm::ivec3 _outDimensions = glm::ivec3(0);
|
||||
std::string _inFilePath;
|
||||
std::string _outFilePath;
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
#endif // __OPENSPACE_MODULE_GALAXY___MILKYWAYCONVERSIONTASK___H__
|
||||
#endif // __OPENSPACE_MODULE_GAIA___READSPECKTASK___H__
|
||||
Reference in New Issue
Block a user