Merge branch 'master' into thesis/2018/dsn

# Conflicts:
#	ext/ghoul
This commit is contained in:
Alexander Bock
2018-12-03 18:10:28 -05:00
222 changed files with 11584 additions and 802 deletions
+6
View File
@@ -20,3 +20,9 @@
[submodule "apps/OpenSpace/ext/sgct"]
path = apps/OpenSpace/ext/sgct
url = https://github.com/opensgct/sgct
[submodule "modules/fitsfilereader/ext/CCfits"]
path = modules/fitsfilereader/ext/CCfits
url = https://github.com/OpenSpace/CCfits.git
[submodule "modules/fitsfilereader/ext/cfitsio"]
path = modules/fitsfilereader/ext/cfitsio
url = https://github.com/OpenSpace/cfitsio.git
+4 -2
View File
@@ -231,8 +231,10 @@ if (OPENSPACE_MODULE_WEBBROWSER AND CEF_ROOT)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${WEBBROWSER_MODULE_PATH}/cmake")
include(webbrowser_helpers)
set_cef_targets("${CEF_ROOT}" OpenSpaceTest)
run_cef_platform_config("${CEF_ROOT}" "${CEF_TARGET}" "${WEBBROWSER_MODULE_PATH}")
if (TARGET OpenSpaceTest)
set_cef_targets("${CEF_ROOT}" OpenSpaceTest)
run_cef_platform_config("${CEF_ROOT}" "${CEF_TARGET}" "${WEBBROWSER_MODULE_PATH}")
endif ()
elseif (OPENSPACE_MODULE_WEBBROWSER)
message(WARNING "Web configured to be included, but no CEF_ROOT was found, please try configuring CMake again.")
endif ()
+13 -10
View File
@@ -143,10 +143,10 @@ LONG WINAPI generateMiniDump(EXCEPTION_POINTERS* exceptionPointers) {
dumpFile.c_str(),
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_WRITE | FILE_SHARE_READ,
0,
nullptr,
CREATE_ALWAYS,
0,
0
nullptr
);
MINIDUMP_EXCEPTION_INFORMATION exceptionParameter;
@@ -358,13 +358,13 @@ void mainPreSyncFunc() {
if (!state.isConnected) {
// Joystick was added
state.isConnected = true;
state.name = SgctEngine->getJoystickName(i);
state.name = sgct::Engine::getJoystickName(i);
std::fill(state.axes.begin(), state.axes.end(), 0.f);
std::fill(state.buttons.begin(), state.buttons.end(), JoystickAction::Idle);
}
const float* axes = SgctEngine->getJoystickAxes(i, &state.nAxes);
const float* axes = sgct::Engine::getJoystickAxes(i, &state.nAxes);
if (state.nAxes > JoystickInputState::MaxAxes) {
LWARNING(fmt::format(
"Joystick/Gamepad {} has {} axes, but only {} axes are supported. "
@@ -375,7 +375,10 @@ void mainPreSyncFunc() {
}
std::memcpy(state.axes.data(), axes, state.nAxes * sizeof(float));
const unsigned char* buttons = SgctEngine->getJoystickButtons(i, &state.nButtons);
const unsigned char* buttons = sgct::Engine::getJoystickButtons(
i,
&state.nButtons
);
if (state.nButtons > JoystickInputState::MaxButtons) {
LWARNING(fmt::format(
@@ -441,7 +444,7 @@ void mainRenderFunc() {
LTRACE("main::mainRenderFunc(begin)");
glm::mat4 viewMatrix = SgctEngine->getCurrentViewMatrix() *
glm::translate(glm::mat4(1.f), SgctEngine->getDefaultUserPtr()->getPos());
glm::translate(glm::mat4(1.f), sgct::Engine::getDefaultUserPtr()->getPos());
glm::mat4 projectionMatrix = SgctEngine->getCurrentProjectionMatrix();
#ifdef OPENVR_SUPPORT
@@ -640,14 +643,14 @@ void setSgctDelegateFunctions() {
sgctDelegate.mousePosition = []() {
int id = sgct::Engine::instance()->getCurrentWindowPtr()->getId();
double posX, posY;
sgct::Engine::instance()->getMousePos(id, &posX, &posY);
sgct::Engine::getMousePos(id, &posX, &posY);
return glm::vec2(posX, posY);
};
sgctDelegate.mouseButtons = [](int maxNumber) {
int id = sgct::Engine::instance()->getCurrentWindowPtr()->getId();
uint32_t result = 0;
for (int i = 0; i < maxNumber; ++i) {
bool button = (sgct::Engine::instance()->getMouseButton(id, i) != 0);
bool button = (sgct::Engine::getMouseButton(id, i) != 0);
if (button) {
result |= (1 << i);
}
@@ -739,10 +742,10 @@ void setSgctDelegateFunctions() {
};
sgctDelegate.isMaster = []() { return sgct::Engine::instance()->isMaster(); };
sgctDelegate.isUsingSwapGroups = []() {
return sgct::Engine::instance()->getCurrentWindowPtr()->isUsingSwapGroups();
return sgct::SGCTWindow::isUsingSwapGroups();
};
sgctDelegate.isSwapGroupMaster = []() {
return sgct::Engine::instance()->getCurrentWindowPtr()->isSwapGroupMaster();
return sgct::SGCTWindow::isSwapGroupMaster();
};
sgctDelegate.viewProjectionMatrix = []() {
return sgct::Engine::instance()->getCurrentModelViewProjectionMatrix();
+4 -8
View File
@@ -68,6 +68,10 @@ local Keybindings = {
local earthAsset = asset.require('scene/solarsystem/planets/earth/earth')
assetHelper.registerInterestingNodes(asset, {
"Earth", "Mars", "Moon", "Sun"
})
asset.onInitialize(function ()
local now = openspace.time.currentWallTime()
-- Jump back one day to show a complete planet
@@ -81,10 +85,6 @@ asset.onInitialize(function ()
openspace.absPath("${DATA}/globebrowsing_servers.lua")
)
openspace.markInterestingNodes({
"Earth", "Mars", "Moon"
})
openspace.addVirtualProperty(
"BoolProperty",
"Show Trails",
@@ -108,8 +108,4 @@ asset.onDeinitialize(function ()
sceneHelper.unbindKeys(Keybindings)
openspace.removeVirtualProperty("*Trail.Renderable.Enabled")
openspace.removeInterestingNodes({
"Earth", "Mars", "Moon"
})
end)
+8 -3
View File
@@ -11,7 +11,7 @@ asset.onInitialize(function ()
helper.addSlide(deck, "${DATA}/test2.jpg")
helper.addSlide(deck, "${DATA}/test3.jpg")
local interpolationDuration = 0
local interpolationDuration = 0.5
function nextSlide()
helper.goToNextSlide(deck, interpolationDuration)
@@ -21,9 +21,14 @@ asset.onInitialize(function ()
helper.goToPreviousSlide(deck, interpolationDuration)
end
function toggleSlides()
helper.toggleSlides(deck, interpolationDuration)
end
helper.setCurrentSlide(deck, 1)
openspace.bindKey("RIGHT", "nextSlide()")
openspace.bindKey("LEFT", "previousSlide()")
openspace.bindKey("RIGHT", "nextSlide()", "Next slide", "Next slide", "/Slides")
openspace.bindKey("LEFT", "previousSlide()", "Previous slide", "Previous slide", "/Slides")
openspace.bindKey("UP", "toggleSlides()", "Toggle slides", "Toggle slides", "/Slides")
end)
+40
View File
@@ -0,0 +1,40 @@
local has_gaia = openspace.modules.isLoaded('gaia')
if not has_gaia then
openspace.printFatal('Could not load scene "' .. asset.filePath .. '" due to missing module "gaia"')
do return end
end
local assetHelper = asset.require('util/asset_helper')
asset.require('default')
-- Augment default scene with gaia data, 3D model and trail
asset.require('scene/milkyway/gaia/gaiastars')
asset.require('scene/milkyway/gaia/apogee')
asset.require('scene/milkyway/gaia/galah')
asset.require('scene/solarsystem/missions/gaia/gaia')
asset.require('scene/solarsystem/missions/gaia/trail')
assetHelper.registerDashboardItems(asset, {
{
Type = "DashboardItemDistance",
Identifier = "GaiaEarthDistance",
GuiName = "Gaia Earth Distance",
SourceType = "Node",
SourceNodeName = "Gaia",
DestinationType = "Node Surface",
DestinationNodeName = "Earth"
}
})
assetHelper.registerInterestingNodes(asset, { "Gaia" })
asset.onInitialize(function ()
openspace.setPropertyValueSingle('Scene.Stars.Renderable.Enabled', false);
openspace.navigation.setCameraState({
Focus = "Gaia",
Position = { 1000000000000.0, 1000000000000.0, 1000000000000.0 },
Rotation = { 0.683224, -0.765934, -0.601234, -0.418073 },
})
end)
+4 -8
View File
@@ -18,6 +18,10 @@ asset.require('util/webgui')
local junoAsset = asset.require('scene/solarsystem/missions/juno/juno')
assetHelper.registerInterestingNodes(asset, {
"Jupiter", "Juno"
})
asset.onInitialize(function ()
openspace.time.setTime("2016-07-01T10:05:00.00")
@@ -28,10 +32,6 @@ asset.onInitialize(function ()
28800, 57600, 115200, 230400, 460800, 921600, 1843200, 3686400, 7372800, 14745600
})
openspace.markInterestingNodes({
"Jupiter", "Juno"
})
openspace.addVirtualProperty(
"BoolProperty",
"Show Trails",
@@ -51,8 +51,4 @@ end)
asset.onDeinitialize(function ()
openspace.removeVirtualProperty("*Trail.Renderable.Enabled")
openspace.removeInterestingNodes({
"Jupiter", "Juno"
})
end)
+4 -13
View File
@@ -37,6 +37,9 @@ assetHelper.registerDashboardItems(asset, {
}
})
assetHelper.registerInterestingNodes(asset, {
"Mercury", "Messenger", "Earth", "Sun"
})
asset.onInitialize(function ()
@@ -49,11 +52,7 @@ asset.onInitialize(function ()
28800, 57600, 115200, 230400, 460800, 921600, 1843200, 3686400, 7372800, 14745600
})
openspace.markInterestingNodes({
"Mercury", "Messenger", "Earth", "Sun"
})
openspace.addVirtualProperty(
openspace.addVirtualProperty(
"BoolProperty",
"Show Trails",
"Scene.*Trail.Renderable.Enabled",
@@ -63,17 +62,9 @@ asset.onInitialize(function ()
nil
)
openspace.navigation.setCameraState({
Focus = "Mercury",
Position = { 526781518487.171326, 257168309890.072144, -1381125204152.817383 },
Rotation = {0.180662, 0.021334, 0.979084, 0.091111},
})
end)
asset.onDeinitialize(function ()
openspace.removeInterestingNodes({
"Mercury", "Messenger", "Earth", "Sun"
})
end)
+32 -12
View File
@@ -18,6 +18,8 @@ asset.require('util/default_joystick')
asset.require('util/webgui')
asset.request('customization/globebrowsing')
-- Custom Keybindings
local Keybindings = {
{
@@ -44,6 +46,18 @@ local Keybindings = {
GuiPath = "/New Horizons",
Local = false
},
{
Key = "F7",
Command =
[[local enabled = openspace.getPropertyValue('Scene.Pluto.Renderable.ProjectionComponent.PerformProjection')
openspace.setPropertyValue('Scene.Pluto.Renderable.ProjectionComponent.PerformProjection', not enabled)
openspace.setPropertyValue('Scene.Charon.Renderable.ProjectionComponent.PerformProjection', not enabled)
openspace.setPropertyValueSingle("Dashboard.NewHorizonsInstruments.Enabled", not enabled)]],
Documentation = "Toggles New Horizons image projection.",
Name = "Toggle NH Image Projection",
GuiPath = "/New Horizons",
Local = false
},
{
Key = "F8",
Command = "openspace.setPropertyValue('Scene.Pluto.Renderable.ProjectionComponent.ClearAllProjections', true);" ..
@@ -65,7 +79,7 @@ local Keybindings = {
},
{
Key = "KP_8",
Command = propertyHelper.increment('Scene.Pluto.Renderable.HeightExaggeration', 5000000),
Command = propertyHelper.increment('Scene.Pluto.Renderable.HeightExaggeration', 5000),
Documentation = "Increases the height map exaggeration on Pluto.",
Name = "Pluto HeightExaggeration +",
GuiPath = "/New Horizons",
@@ -73,7 +87,7 @@ local Keybindings = {
},
{
Key = "KP_2",
Command = propertyHelper.decrement('Scene.Pluto.Renderable.HeightExaggeration', 5000000),
Command = propertyHelper.decrement('Scene.Pluto.Renderable.HeightExaggeration', 5000),
Documentation = "Decreases the height map exaggeration on Pluto.",
Name = "Pluto HeightExaggeration -",
GuiPath = "/New Horizons",
@@ -81,7 +95,7 @@ local Keybindings = {
},
{
Key = "KP_9",
Command = propertyHelper.increment('Scene.Charon.Renderable.HeightExaggeration', 5000000),
Command = propertyHelper.increment('Scene.Charon.Renderable.HeightExaggeration', 5000),
Documentation = "Increases the height map exaggeration on Charon.",
Name = "Charon HeightExaggeration +",
GuiPath = "/New Horizons",
@@ -89,7 +103,7 @@ local Keybindings = {
},
{
Key = "KP_3",
Command = propertyHelper.decrement('Scene.Charon.Renderable.HeightExaggeration', 5000000),
Command = propertyHelper.decrement('Scene.Charon.Renderable.HeightExaggeration', 5000),
Documentation = "Decreases the height map exaggeration on Charon.",
Name = "Charon HeightExaggeration -",
GuiPath = "/New Horizons",
@@ -140,13 +154,22 @@ local Keybindings = {
Local = false
},
{
Key = "t",
Key = "Shift+t",
Command = renderableHelper.toggle('Scene.PlutoShadow') .. renderableHelper.toggle('Scene.CharonShadow'),
Documentation = "Toggles the visibility of the shadow visualization of Pluto and Charon.",
Name = "Toggle Shadows",
GuiPath = "/New Horizons",
Local = false
},
{
Key = "t",
Command = renderableHelper.toggle('Scene.NewHorizonsTrailPluto'),
Documentation = "Toggles the trail of New Horizons.",
Name = "Toggle NH Trail",
GuiPath = "/New Horizons",
Local = false
}
}
local NewHorizonsAsset = asset.require('scene/solarsystem/missions/newhorizons/model')
@@ -174,6 +197,10 @@ assetHelper.registerDashboardItems(asset, {
}
})
assetHelper.registerInterestingNodes(asset, {
"Pluto", "NewHorizons", "Charon"
})
asset.onInitialize(function ()
openspace.time.setTime("2015-07-14T08:00:00.00")
sceneHelper.bindKeys(Keybindings)
@@ -185,10 +212,6 @@ asset.onInitialize(function ()
2160, 4320, 8640
})
openspace.markInterestingNodes({
"Pluto", "NewHorizons", "Charon"
})
openspace.setPropertyValueSingle('NavigationHandler.OrbitalNavigator.FollowFocusNodeRotationDistance', 20.000000);
openspace.addVirtualProperty(
@@ -212,7 +235,4 @@ asset.onDeinitialize(function ()
sceneHelper.unbindKeys(Keybindings)
openspace.removeVirtualProperty("*Trail.Renderable.Enabled")
openspace.removeInterestingNodes({
"Pluto", "NewHorizons", "Charon"
})
end)
+6 -7
View File
@@ -19,6 +19,8 @@ asset.require('util/default_joystick')
asset.require('util/webgui')
asset.request('customization/globebrowsing')
-- Custom Keybindings
local Keybindings = {
{
@@ -109,6 +111,10 @@ assetHelper.registerDashboardItems(asset, {
}
})
assetHelper.registerInterestingNodes(asset, {
"67P", "Rosetta", "Philae"
})
asset.onInitialize(function ()
openspace.time.setTime("2014-08-01T03:05:00.000")
sceneHelper.bindKeys(Keybindings)
@@ -120,10 +126,6 @@ asset.onInitialize(function ()
28800, 57600, 115200, 230400, 460800, 921600, 1843200, 3686400, 7372800, 14745600
})
openspace.markInterestingNodes({
"67P", "Rosetta", "Philae"
})
openspace.addVirtualProperty(
"BoolProperty",
"Show Trails",
@@ -147,7 +149,4 @@ asset.onDeinitialize(function ()
sceneHelper.unbindKeys(Keybindings)
openspace.removeVirtualProperty("*Trail.Renderable.Enabled")
openspace.removeInterestingNodes({
"67PBarycenter", "Rosetta", "Philae"
})
end)
@@ -20,10 +20,10 @@ local colorLUT = asset.syncedResource({
Name = "Stars Color Table",
Type = "HttpSynchronization",
Identifier = "stars_colormap",
Version = 1
Version = 2
})
local object = {
local stars = {
Identifier = "Stars",
Renderable = {
Type = "RenderableStars",
@@ -36,6 +36,4 @@ local object = {
}
}
assetHelper.registerSceneGraphNodesAndExport(asset, { object })
assetHelper.registerSceneGraphNodesAndExport(asset, { stars })
@@ -0,0 +1,46 @@
local assetHelper = asset.require('util/asset_helper')
local textures = asset.syncedResource({
Name = "Stars Textures",
Type = "HttpSynchronization",
Identifier = "stars_textures",
Version = 1
})
local speck = asset.syncedResource({
Name = "Apogee Speck Files",
Type = "HttpSynchronization",
Identifier = "gaia_apogee",
Version = 1
})
local colorLUT = asset.syncedResource({
Name = "Stars Color Table",
Type = "HttpSynchronization",
Identifier = "stars_colormap",
Version = 2
})
local gaia_abundance_apogee = {
Identifier = "Gaia Abundance Apogee",
Renderable = {
Type = "RenderableStars",
Enabled = false,
File = speck .. "/GaiaAbundApogee.speck",
ColorOption = "Other Data",
OtherData = "FeH",
ScaleFactor = 100,
Texture = textures .. "/halo.png",
ColorMap = colorLUT .. "/colorbv.cmap",
OtherDataColorMap = colorLUT .. "/viridis.cmap",
StaticFilter = -9999,
StaticFilterReplacement = 0.0
},
GUI = {
Path = "/Milky Way/Gaia"
}
}
assetHelper.registerSceneGraphNodesAndExport(asset, { gaia_abundance_apogee })
@@ -0,0 +1,19 @@
-- Download a dataset of 618 million stars (28 GB), already preprocessed and stored in a binary octree.
-- The octree was generated from the full DR2 by filtering away all stars with a parallax error higher than 0.5
-- Max Star Per Node = 50,000 and max distance = 500kpc
asset.syncedResource({
Name = "Gaia DR2 618M Octree",
Type = "HttpSynchronization",
Identifier = "gaia_stars_618M_octree",
Version = 1
})
-- Download the full DR2 dataset with 24 values per star (preprocessed with theReadFitsTask (gaia_read.task) into 8 binary files).
-- From these files new subsets can be created with the ConstructOctreeTask (gaia_octree.task).
-- Total size of download is 151 GB.
asset.syncedResource({
Name = "Gaia DR2 Full Raw",
Type = "HttpSynchronization",
Identifier = "gaia_stars_dr2_raw",
Version = 1
})
@@ -0,0 +1,60 @@
local assetHelper = asset.require("util/asset_helper")
local textures = asset.syncedResource({
Name = "Stars Textures",
Type = "HttpSynchronization",
Identifier = "stars_textures",
Version = 1
})
local colorLUT = asset.syncedResource({
Name = "Stars Color Table",
Type = "HttpSynchronization",
Identifier = "stars_colormap",
Version = 1
})
-- Download a preprocessed binary octree of Radial Velocity subset values per star (preprocessed into 8 binary files).
local starsFolder = asset.syncedResource({
Name = "Gaia Stars RV",
Type = "HttpSynchronization",
Identifier = "gaia_stars_rv_octree",
Version = 1
})
local GaiaStars = {
Identifier = "GaiaStars",
Renderable = {
Type = "RenderableGaiaStars",
File = starsFolder .. "/",
FileReaderOption = "StreamOctree",
RenderOption = "Motion",
ShaderOption = "Point_SSBO",
Texture = textures .. "/halo.png",
ColorMap = colorLUT .. "/colorbv.cmap",
LuminosityMultiplier = 35,
MagnitudeBoost = 25,
CutOffThreshold = 38,
BillboardSize = 1,
CloseUpBoostDist = 250,
Sharpness = 1.45,
LodPixelThreshold = 0,
MaxGpuMemoryPercent = 0.24,
MaxCpuMemoryPercent = 0.4,
FilterSize = 5,
Sigma = 0.5,
AdditionalNodes = {3.0, 2.0},
FilterPosX = {0.0, 0.0},
FilterPosY = {0.0, 0.0},
FilterPosZ = {0.0, 0.0},
FilterGMag = {20.0, 20.0},
FilterBpRp = {0.0, 0.0},
FilterDist = {9.0, 9.0},
},
GUI = {
Name = "Gaia Stars",
Path = "/Milky Way"
}
}
assetHelper.registerSceneGraphNodesAndExport(asset, { GaiaStars })
@@ -0,0 +1,46 @@
local assetHelper = asset.require('util/asset_helper')
local textures = asset.syncedResource({
Name = "Stars Textures",
Type = "HttpSynchronization",
Identifier = "stars_textures",
Version = 1
})
local speck = asset.syncedResource({
Name = "Galah Speck Files",
Type = "HttpSynchronization",
Identifier = "gaia_galah",
Version = 1
})
local colorLUT = asset.syncedResource({
Name = "Stars Color Table",
Type = "HttpSynchronization",
Identifier = "stars_colormap",
Version = 2
})
local gaia_abundance_galah = {
Identifier = "Gaia Abundance Galah",
Renderable = {
Type = "RenderableStars",
Enabled = false,
File = speck .. "/GaiaAbundGalah.speck",
Texture = textures .. "/halo.png",
ColorOption = "Other Data",
OtherData = "FeH",
ScaleFactor = 100,
ColorMap = colorLUT .. "/colorbv.cmap",
OtherDataColorMap = colorLUT .. "/viridis.cmap",
StaticFilter = -9999,
StaticFilterReplacement = 0.0
},
GUI = {
Path = "/Milky Way/Gaia"
}
}
assetHelper.registerSceneGraphNodesAndExport(asset, { gaia_abundance_galah })
@@ -20,7 +20,7 @@ local colorLUT = asset.syncedResource({
Name = "Stars Color Table",
Type = "HttpSynchronization",
Identifier = "stars-denver_colormap",
Version = 1
Version = 2
})
local object = {
@@ -0,0 +1,67 @@
local assetHelper = asset.require('util/asset_helper')
local transforms = asset.require('./transforms')
local sunTransforms = asset.require('scene/solarsystem/sun/transforms')
local textures = asset.syncedResource({
Name = "Gaia Textures",
Type = "HttpSynchronization",
Identifier = "gaia_textures",
Version = 1
})
local model = asset.syncedResource({
Name = "Gaia Model",
Type = "HttpSynchronization",
Identifier = "gaia_model",
Version = 1
})
local Gaia = {
Identifier = "Gaia",
Parent = transforms.GaiaPosition.Identifier,
Transform = {
Rotation = {
Type = "FixedRotation",
Attached = "Gaia",
XAxis = { 1.0, 0.0, 0.0 },
XAxisOrthogonal = true,
YAxis = "Sun",
YAxisInverted = true
},
Scale = {
Type = "StaticScale",
Scale = 10.0
}
},
-- X Orthogonal
Renderable = {
Type = "RenderableModel",
Body = "GAIA",
Geometry = {
Type = "MultiModelGeometry",
GeometryFile = model .. "/gaia.obj"
},
ColorTexture = textures .. "/gaia-baked.png",
LightSources = {
{
Type = "SceneGraphLightSource",
Identifier = "Sun",
Node = sunTransforms.SolarSystemBarycenter.Identifier,
Intensity = 0.3
},
{
Identifier = "Camera",
Type = "CameraLightSource",
Intensity = 0.4
}
}
},
GUI = {
Name = "Gaia",
Path = "/Solar System/Missions/Gaia"
}
}
assetHelper.registerSceneGraphNodesAndExport(asset, { Gaia })
@@ -0,0 +1,64 @@
local assetHelper = asset.require('util/asset_helper')
local earthTransforms = asset.require('scene/solarsystem/planets/earth/transforms')
local sunTransforms = asset.require('scene/solarsystem/sun/transforms')
local trail = asset.syncedResource({
Name = "Gaia Trail",
Type = "HttpSynchronization",
Identifier = "gaia_trail",
Version = 2
})
local GaiaTrail = {
Identifier = "GaiaTrail",
Parent = earthTransforms.EarthBarycenter.Identifier,
Renderable = {
Type = "RenderableTrailTrajectory",
Enabled = false,
Translation = {
Type = "HorizonsTranslation",
HorizonsTextFile = trail .. "/gaia_orbit_horizons.dat"
},
Color = { 0.0, 0.8, 0.7 },
ShowFullTrail = false,
StartTime = "2013 DEC 19 09:55:10",
EndTime = "2019 JUN 20 05:55:10",
PointSize = 5,
SampleInterval = 12000,
TimeStampSubsampleFactor = 1,
EnableFade = false,
Rendering = "Lines"
},
GUI = {
Name = "Gaia Trail",
Path = "/Solar System/Missions/Gaia"
}
}
local GaiaTrailEclip = {
Identifier = "GaiaTrail_Eclip",
Parent = sunTransforms.SolarSystemBarycenter.Identifier,
Renderable = {
Type = "RenderableTrailTrajectory",
Enabled = false,
Translation = {
Type = "HorizonsTranslation",
HorizonsTextFile = trail .. "/gaia_orbit_horizons_sun.dat"
},
Color = { 1.0, 0.0, 0.0 },
ShowFullTrail = false,
StartTime = "2013 DEC 19 09:55:10",
EndTime = "2019 JUN 20 05:55:10",
PointSize = 5,
SampleInterval = 6000,
TimeStampSubsampleFactor = 1,
EnableFade = false,
Rendering = "Lines"
},
GUI = {
Name = "Gaia Ecliptic Trail",
Path = "/Solar System/Missions/Gaia"
}
}
assetHelper.registerSceneGraphNodesAndExport(asset, { GaiaTrail, GaiaTrailEclip } )
@@ -0,0 +1,27 @@
local assetHelper = asset.require('util/asset_helper')
local earthTransforms = asset.require('scene/solarsystem/planets/earth/transforms')
local trail = asset.syncedResource({
Name = "Gaia Trail",
Type = "HttpSynchronization",
Identifier = "gaia_trail",
Version = 1
})
local GaiaPosition = {
Identifier = "GaiaPosition",
Parent = earthTransforms.EarthBarycenter.Identifier,
Transform = {
Translation = {
Type = "HorizonsTranslation",
HorizonsTextFile = trail .. "/gaia_orbit_horizons.dat"
},
},
GUI = {
Name = "Position",
Path = "/Solar System/Missions/Gaia"
}
}
assetHelper.registerSceneGraphNodesAndExport(asset, { GaiaPosition })
@@ -5,6 +5,8 @@ asset.request('./trail')
local kernel = asset.require('../kernels').jup310
local map_service_configs = asset.localResource("map_service_configs")
local textures = asset.syncedResource({
Name = "Europa Textures",
@@ -39,8 +41,15 @@ local Europa = {
{
Identifier = "Texture",
FilePath = textures .. "/europa.jpg",
-- Enabled = true
},
{
Identifier = "Voyager_Global_Mosaic",
Name = "Voyager Global Mosaic [Sweden]",
FilePath = map_service_configs .. "/LiU/Voyager_GalileoSSI_global_mosaic_500m.wms",
BlendMode = "Color",
Enabled = true
}
},
}
}
},
@@ -0,0 +1,20 @@
<GDAL_WMS>
<Service name="TMS">
<ServerUrl>http://wms.itn.liu.se/Europa/Voyager_GalileoSSI_global_mosaic_500m/tile/${z}/${y}/${x}</ServerUrl>
</Service>
<DataWindow>
<UpperLeftX>-180.0</UpperLeftX>
<UpperLeftY>90.0</UpperLeftY>
<LowerRightX>180.0</LowerRightX>
<LowerRightY>-90.0</LowerRightY>
<SizeX>19631</SizeX>
<SizeY>9816</SizeY>
<TileLevel>7</TileLevel>
<YOrigin>top</YOrigin>
</DataWindow>
<Projection>EPSG:4326</Projection>
<BlockSizeX>256</BlockSizeX>
<BlockSizeY>256</BlockSizeY>
<BandsCount>1</BandsCount>
<MaxConnections>10</MaxConnections>
</GDAL_WMS>
@@ -10,12 +10,13 @@
<SizeX>46080</SizeX>
<SizeY>23040</SizeY>
<TileLevel>6</TileLevel>
<YOrigin>bottom</YOrigin>
<YOrigin>top</YOrigin>
</DataWindow>
<DataType>Int16</DataType>
<Projection>GEOGCS["GCS_Mars_2000_Sphere",DATUM["D_Mars_2000_Sphere",SPHEROID["Mars_2000_Sphere_IAU_IAG",3396190.0,0.0]],PRIMEM["Reference_Meridian",0.0],UNIT["Degree",0.0174532925199433]]</Projection>
<BlockSizeX>256</BlockSizeX>
<BlockSizeY>256</BlockSizeY>
<BlockSizeX>360</BlockSizeX>
<BlockSizeY>360</BlockSizeY>
<BandsCount>1</BandsCount>
<MaxConnections>10</MaxConnections>
<Timeout>5</Timeout>
</GDAL_WMS>
@@ -12,6 +12,8 @@ local textures = asset.syncedResource({
Version = 1
})
local mapServiceConfigsPath = asset.localResource("map_service_configs")
local Enceladus = {
Identifier = "Enceladus",
Parent = transforms.SaturnBarycenter.Identifier,
@@ -37,8 +39,13 @@ local Enceladus = {
{
Identifier = "Texture",
FilePath = textures .. "/enceladus.jpg",
Enabled = true
}
},
{
Identifier = "Global_Mosaic_100m_HPF",
Name = "Cassini Global Mosaic 100m HPF",
FilePath = mapServiceConfigsPath .. "/Cassini_ISS_Global_Mosaic_100m_HPF.wms",
Enabled = true,
},
}
}
},
@@ -0,0 +1,20 @@
<GDAL_WMS>
<Service name="TMS">
<ServerUrl>http://wms.itn.liu.se/Enceladus/Cassini_ISS_Global_Mosaic_100m_HPF/tile/${z}/${y}/${x}</ServerUrl>
</Service>
<DataWindow>
<UpperLeftX>-180.0</UpperLeftX>
<UpperLeftY>90.0</UpperLeftY>
<LowerRightX>180.0</LowerRightX>
<LowerRightY>-90.0</LowerRightY>
<SizeX>15840</SizeX>
<SizeY>7920</SizeY>
<TileLevel>5</TileLevel>
<YOrigin>top</YOrigin>
</DataWindow>
<Projection>EPSG:4326</Projection>
<BlockSizeX>512</BlockSizeX>
<BlockSizeY>512</BlockSizeY>
<BandsCount>1</BandsCount>
<MaxConnections>10</MaxConnections>
</GDAL_WMS>
@@ -0,0 +1,20 @@
<GDAL_WMS>
<Service name="TMS">
<ServerUrl>http://wms.itn.liu.se/Titan/ISS_P19658_Mosaic_Global_4km/tile/${z}/${y}/${x}</ServerUrl>
</Service>
<DataWindow>
<UpperLeftX>-180.0</UpperLeftX>
<UpperLeftY>90.0</UpperLeftY>
<LowerRightX>180.0</LowerRightX>
<LowerRightY>-90.0</LowerRightY>
<SizeX>4040</SizeX>
<SizeY>2020</SizeY>
<TileLevel>4</TileLevel>
<YOrigin>top</YOrigin>
</DataWindow>
<Projection>EPSG:4326</Projection>
<BlockSizeX>256</BlockSizeX>
<BlockSizeY>256</BlockSizeY>
<BandsCount>1</BandsCount>
<MaxConnections>10</MaxConnections>
</GDAL_WMS>
@@ -4,6 +4,7 @@ local kernel = asset.require('../kernels').sat375
asset.request('./trail')
local map_service_configs = asset.localResource("map_service_configs")
local textures = asset.syncedResource({
Type = "HttpSynchronization",
@@ -37,6 +38,12 @@ local Titan = {
{
Identifier = "Texture",
FilePath = textures .. "/titan.jpg",
-- Enabled = true
},
{
Identifier = "Cassini_ISS_Global_Mosaic_4km_LiU",
Name = "Cassini ISS Global Mosaic [Sweden]",
FilePath = map_service_configs .. "/LiU/ISS_P19658_Mosaic_Global_4km.wms",
Enabled = true
}
}
+10
View File
@@ -88,6 +88,15 @@ local registerSceneGraphNodesAndExport = function (sceneAsset, nodes, override)
end
end
local registerInterestingNodes = function (sceneAsset, nodes)
sceneAsset.onInitialize(function ()
openspace.markInterestingNodes(nodes)
end)
sceneAsset.onDeinitialize(function ()
openspace.removeInterestingNodes(nodes)
end)
end
local requireAll = function (sceneAsset, directory)
function string.ends(String,End)
return End=='' or string.sub(String,-string.len(End))==End
@@ -125,5 +134,6 @@ asset.export("registerSceneGraphNodes", registerSceneGraphNodes)
asset.export("registerSceneGraphNodesAndExport", registerSceneGraphNodesAndExport)
asset.export("registerSpiceKernels", registerSpiceKernels)
asset.export("registerDashboardItems", registerDashboardItems)
asset.export("registerInterestingNodes", registerInterestingNodes)
asset.export("requireAll", requireAll)
asset.export("requestAll", requestAll)
+4 -30
View File
@@ -3,36 +3,10 @@ local propertyHelper = asset.require('./property_helper')
local Keybindings = {
{
Key = "F2",
Name = "Show Scene Menu",
Command =
[[local b = openspace.getPropertyValue('Modules.ImGUI.Main.SceneProperties.Enabled');
local c = openspace.getPropertyValue('Modules.ImGUI.Main.IsHidden');
openspace.setPropertyValue('Modules.ImGUI.*.Enabled', false);
if b and c then
-- This can happen if the main properties window is enabled, the main gui is enabled
-- and then closed again. So the main properties window is enabled, but also all
-- windows are hidden
openspace.setPropertyValueSingle('Modules.ImGUI.Main.IsHidden', false);
openspace.setPropertyValueSingle('Modules.ImGUI.Main.SceneProperties.Enabled', true);
openspace.setPropertyValueSingle('Modules.ImGUI.Main.SpaceTime.Enabled', true);
else
openspace.setPropertyValueSingle('Modules.ImGUI.Main.SceneProperties.Enabled', not b);
openspace.setPropertyValueSingle('Modules.ImGUI.Main.SpaceTime.Enabled', not b);
openspace.setPropertyValueSingle('Modules.ImGUI.Main.IsHidden', b);
end]],
Documentation = "Shows or hides the properties window",
GuiPath = "/Native GUI",
Local = true
},
{
Key = "F3",
Name = "Show Global Menu",
Command =
[[local b = openspace.getPropertyValue('Modules.ImGUI.Main.Enabled');
openspace.setPropertyValueSingle('Modules.ImGUI.Main.Enabled', not b);
openspace.setPropertyValueSingle('Modules.ImGUI.Main.IsHidden', b);]],
Documentation = "Shows or hides the entire user interface",
Key = "F1",
Name = "Show Native GUI",
Command = propertyHelper.invert('Modules.ImGUI.Main.Enabled'),
Documentation = "Shows or hides the native UI",
GuiPath = "/Native GUI",
Local = true
},
+28 -1
View File
@@ -4,6 +4,7 @@ local createDeck = function (identifier, defaultRenderableProperties)
IdentifierPrefix = identifier,
CurrentSlideIndex = 1,
DefaultRenderableProperties = defaultRenderableProperties,
Visible = true
}
end
@@ -49,6 +50,10 @@ local setCurrentSlide = function (deck, index, interpolationDuration)
deck.CurrentSlideIndex = index
if not deck.Visible then
return
end
for i, identifier in pairs(deck.SlideIdentifiers) do
local opacity = 0
if (index == i) then
@@ -56,7 +61,7 @@ local setCurrentSlide = function (deck, index, interpolationDuration)
end
openspace.setPropertyValueSingle(
"ScreenSpace." .. identifier .. ".Alpha", opacity,
interpolationDuration)
interpolationDuration, "QuadraticEaseOut")
end
end
@@ -68,9 +73,31 @@ local goToPreviousSlide = function (deck, interpolationDuration)
setCurrentSlide(deck, deck.CurrentSlideIndex - 1, interpolationDuration)
end
local toggleSlides = function (deck, interpolationDuration)
deck.Visible = not deck.Visible
if deck.Visible then
for i, identifier in pairs(deck.SlideIdentifiers) do
local opacity = 0
if (i == deck.CurrentSlideIndex) then
opacity = 1
end
openspace.setPropertyValueSingle(
"ScreenSpace." .. identifier .. ".Alpha", opacity,
interpolationDuration, "QuadraticEaseOut")
end
else
for i, identifier in pairs(deck.SlideIdentifiers) do
openspace.setPropertyValueSingle(
"ScreenSpace." .. identifier .. ".Alpha", 0,
interpolationDuration, "QuadraticEaseOut")
end
end
end
asset.export('createDeck', createDeck)
asset.export('removeDeck', removeDeck)
asset.export('addSlide', addSlide)
asset.export('setCurrentSlide', setCurrentSlide)
asset.export('goToNextSlide', goToNextSlide)
asset.export('goToPreviousSlide', goToPreviousSlide)
asset.export('toggleSlides', toggleSlides)
+6
View File
@@ -0,0 +1,6 @@
return {
{
Type = "SyncAssetTask",
Asset = "scene/milkyway/gaia/gaia_dr2_download_stars"
}
}
+45
View File
@@ -0,0 +1,45 @@
local dataFolder = "E:/gaia_sync_data"
return {
{
Type = "ConstructOctreeTask",
InFileOrFolderPath = dataFolder .. "/Gaia_DR2_full_24columns/",
OutFileOrFolderPath = dataFolder .. "/DR2_full_Octree_test_50,50/",
MaxDist = 500,
MaxStarsPerNode = 50000,
SingleFileInput = false,
-- Specify filter thresholds
--FilterPosX = {0.0, 0.0},
--FilterPosY = {0.0, 0.0},
--FilterPosZ = {0.0, 0.0},
FilterGMag = {20.0, 20.0},
FilterBpRp = {0.0, 0.0},
--FilterVelX = {0.0, 0.0},
--FilterVelY = {0.0, 0.0},
--FilterVelZ = {0.0, 0.0},
--FilterBpMag = {20.0, 20.0},
--FilterRpMag = {20.0, 20.0},
--FilterBpG = {0.0, 0.0},
--FilterGRp = {0.0, 0.0},
--FilterRa = {0.0, 0.0},
--FilterRaError = {0.0, 0.0},
--FilterDec = {0.0, 0.0},
--FilterDecError = {0.0, 0.0},
FilterParallax = {0.01, 0.0},
FilterParallaxError = {0.00001, 0.5},
--FilterPmra = {0.0, 0.0},
--FilterPmraError = {0.0, 0.0},
--FilterPmdec = {0.0, 0.0},
--FilterPmdecError = {0.0, 0.0},
--FilterRv = {0.0, 0.0},
--FilterRvError = {0.0, 0.0},
},
-- {
-- Type = "ConstructOctreeTask",
-- InFileOrFolderPath = dataFolder .. "/AMNH/Binary/GaiaUMS.bin",
-- OutFileOrFolderPath = dataFolder .. "/AMNH/Octree/GaiaUMS_Octree.bin",
-- MaxDist = 10,
-- MaxStarsPerNode = 20000,
-- SingleFileInput = true,
-- },
}
+16
View File
@@ -0,0 +1,16 @@
local dataFolder = "E:/gaia_sync_data"
return {
{
Type = "ReadFitsTask",
InFileOrFolderPath = "L:/Gaia_DR2/gaia_source/fits/",
OutFileOrFolderPath = dataFolder .. "/Gaia_DR2_full_24columns/",
SingleFileProcess = false,
ThreadsToUse = 8,
},
--{
-- Type = "ReadSpeckTask",
-- InFilePath = dataFolder .. "/AMNH/GaiaUMS/GaiaUMS.speck",
-- OutFilePath = dataFolder .. "/AMNH/Binary/GaiaUMS.bin",
--},
}
@@ -308,21 +308,19 @@ void testSpecificationAndThrow(const Documentation& documentation,
namespace ghoul {
template <>
std::string to_string(const openspace::documentation::TestResult& testResult);
std::string to_string(const openspace::documentation::TestResult& value);
template <>
std::string to_string(const openspace::documentation::TestResult::Offense& offense);
std::string to_string(const openspace::documentation::TestResult::Offense& value);
template <>
std::string to_string(
const openspace::documentation::TestResult::Offense::Reason& reason);
std::string to_string(const openspace::documentation::TestResult::Offense::Reason& value);
template <>
std::string to_string(const openspace::documentation::TestResult::Warning& warning);
std::string to_string(const openspace::documentation::TestResult::Warning& value);
template <>
std::string to_string(
const openspace::documentation::TestResult::Warning::Reason& reason);
std::string to_string(const openspace::documentation::TestResult::Warning::Reason& value);
} // namespace ghoul
@@ -106,7 +106,8 @@ private:
namespace ghoul {
template <>
std::string to_string(const openspace::interaction::JoystickCameraStates::AxisType& type);
std::string to_string(
const openspace::interaction::JoystickCameraStates::AxisType& value);
template <>
openspace::interaction::JoystickCameraStates::AxisType
@@ -113,7 +113,7 @@ struct JoystickInputStates : public std::array<JoystickInputState, MaxJoysticks>
namespace ghoul {
template <>
std::string to_string(const openspace::interaction::JoystickAction& action);
std::string to_string(const openspace::interaction::JoystickAction& value);
template <>
openspace::interaction::JoystickAction from_string(const std::string& str);
@@ -104,7 +104,7 @@ private:
SceneGraphNode* _focusNode = nullptr;
glm::dvec3 _previousFocusNodePosition;
glm::dquat _previousFocusNodeRotation;
double _currentCameraToSurfaceDistance;
double _currentCameraToSurfaceDistance = 0.0;
bool _directlySetStereoDistance = false;
Interpolator<double> _rotateToFocusNodeInterpolator;
@@ -69,7 +69,7 @@ public:
* \param filename file saved with recorded keyframes.
* \returns true if recording to file starts without errors.
*/
bool startRecording(std::string filename);
bool startRecording(const std::string& filename);
/**
* Starts a recording session, which will save data to the provided filename
@@ -160,10 +160,10 @@ private:
};
ExternInteraction _externInteract;
bool _isRecording = false;
double _timestampRecordStarted;
double _timestampPlaybackStarted_application;
double _timestampPlaybackStarted_simulation;
double _timestampApplicationStarted_simulation;
double _timestampRecordStarted = 0.0;
double _timestampPlaybackStarted_application = 0.0;
double _timestampPlaybackStarted_simulation = 0.0;
double _timestampApplicationStarted_simulation = 0.0;
bool hasCameraChangedFromPrev(datamessagestructures::CameraKeyframe kfNew);
double appropriateTimestamp(double timeOs, double timeRec, double timeSim);
double equivalentSimulationTime(double timeOs, double timeRec, double timeSim);
@@ -179,7 +179,7 @@ private:
void writeToFileBuffer(std::vector<char>& cvec);
void writeToFileBuffer(const unsigned char c);
void writeToFileBuffer(bool b);
void saveStringToFile(const std::string s);
void saveStringToFile(const std::string& s);
void saveKeyframeToFileBinary(unsigned char* bufferSource, size_t size);
void findFirstCameraKeyframeInTimeline();
std::string readHeaderElement(size_t readLen_chars);
+1 -1
View File
@@ -95,7 +95,7 @@ private:
void setHostName(const std::string& hostName);
void setNConnections(size_t nConnections);
double convertTimestamp(double originalTime);
double convertTimestamp(double messageTimestamp);
void analyzeTimeDifference(double messageTimestamp);
properties::StringProperty _password;
+8 -9
View File
@@ -65,10 +65,9 @@ private:
ParallelConnection::Message message;
};
bool isConnected(std::shared_ptr<Peer> peer) const;
bool isConnected(const Peer& peer) const;
void sendMessage(std::shared_ptr<Peer> peer,
ParallelConnection::MessageType messageType,
void sendMessage(Peer& peer, ParallelConnection::MessageType messageType,
const std::vector<char>& message);
void sendMessageToAll(ParallelConnection::MessageType messageType,
@@ -77,17 +76,17 @@ private:
void sendMessageToClients(ParallelConnection::MessageType messageType,
const std::vector<char>& message);
void disconnect(std::shared_ptr<Peer> peer);
void setName(std::shared_ptr<Peer> peer, std::string name);
void disconnect(Peer& peer);
void setName(Peer& peer, std::string name);
void assignHost(std::shared_ptr<Peer> newHost);
void setToClient(std::shared_ptr<Peer> peer);
void setToClient(Peer& peer);
void setNConnections(size_t nConnections);
void sendConnectionStatus(std::shared_ptr<Peer> peer);
void sendConnectionStatus(Peer& peer);
void handleAuthentication(std::shared_ptr<Peer> peer, std::vector<char> message);
void handleData(std::shared_ptr<Peer> peer, std::vector<char> data);
void handleData(const Peer& peer, std::vector<char> data);
void handleHostshipRequest(std::shared_ptr<Peer> peer, std::vector<char> message);
void handleHostshipResignation(std::shared_ptr<Peer> peer, std::vector<char> data);
void handleHostshipResignation(Peer& peer);
void handleDisconnection(std::shared_ptr<Peer> peer);
void handleNewPeers();
@@ -45,14 +45,14 @@ struct PerformanceLayout {
float updateRotation[NumberValues];
float updateScaling[NumberValues];
};
SceneGraphPerformanceLayout sceneGraphEntries[MaxValues];
SceneGraphPerformanceLayout sceneGraphEntries[MaxValues] = {};
int16_t nScaleGraphEntries = 0;
struct FunctionPerformanceLayout {
char name[LengthName];
float time[NumberValues];
};
FunctionPerformanceLayout functionEntries[MaxValues];
FunctionPerformanceLayout functionEntries[MaxValues] = {};
int16_t nFunctionEntries = 0;
};
@@ -42,8 +42,6 @@ public:
static void CreateGlobalSharedMemory();
static void DestroyGlobalSharedMemory();
~PerformanceManager();
void setEnabled(bool enabled);
bool isEnabled() const;
+13 -5
View File
@@ -102,13 +102,21 @@ public:
void addOption(int value, std::string desc);
/**
* Adds multiple options to the OptionProperty. Each value in the vector consists of
* an integer value and a string description.
*
* \param options Pairs of <option, description> that are added to the OptionProperty
*/
* Adds multiple options to the OptionProperty. Each value in the vector consists of
* an integer value and a string description.
*
* \param options Pairs of <option, description> that are added to the OptionProperty
*/
void addOptions(std::vector<std::pair<int, std::string>> options);
/**
* Adds multiple options to the OptionProperty. Each value in the vector is assigned
* to its location.
*
* \param options A list of options that should be added to the OptionProperty
*/
void addOptions(std::vector<std::string> options);
/**
* Returns the list of available options.
*
@@ -160,6 +160,12 @@ public:
*/
bool hasProperty(const std::string& uri) const;
/**
* This method checks if a Property exists in this PropertyOwner.
* \return <code>true</code> if the Property existed, <code>false</code> otherwise.
*/
bool hasProperty(const Property* prop) const;
void setPropertyOwner(PropertyOwner* owner) { _owner = owner; }
PropertyOwner* owner() const { return _owner; }
+2 -3
View File
@@ -28,6 +28,7 @@
#include <openspace/properties/propertyowner.h>
#include <openspace/properties/scalar/boolproperty.h>
#include <openspace/rendering/dashboarditem.h>
#include <ghoul/glm.h>
#include <memory>
#include <vector>
@@ -36,12 +37,10 @@ namespace openspace {
namespace scripting { struct LuaLibrary; }
class DashboardItem;
class Dashboard : public properties::PropertyOwner {
public:
Dashboard();
~Dashboard();
~Dashboard() = default;
void render(glm::vec2& penPosition);
+2 -1
View File
@@ -68,6 +68,7 @@ public:
void tickItem();
enum class Phase {
PreStart,
Construction,
Synchronization,
Initialization
@@ -97,7 +98,7 @@ private:
bool _showNodeNames;
bool _showProgressbar;
Phase _phase;
Phase _phase = Phase::PreStart;
std::atomic_int _iProgress = 0;
std::atomic_int _nItems = 0;
+1 -1
View File
@@ -141,7 +141,7 @@ public:
private:
void setState(State state);
void requiredAssetChangedState(std::shared_ptr<Asset> asset, Asset::State childState);
void requiredAssetChangedState(Asset::State childState);
void requestedAssetChangedState(Asset* child, Asset::State childState);
bool isSyncResolveReady();
+1 -2
View File
@@ -58,8 +58,7 @@ public:
* \param component The optional compoment that caused this exception to be thrown
* \pre message may not be empty
*/
explicit InvalidSceneError(const std::string& msg,
const std::string& comp = "");
explicit InvalidSceneError(std::string msg, std::string comp = "");
};
/// This struct describes a time that has some intrinsic interesting-ness to this
@@ -289,6 +289,8 @@ constexpr double convertDistance(double meters, DistanceUnit requestedUnit) {
}
}
float convertMasPerYearToMeterPerSecond(float masPerYear, float parallax);
} // namespace openspace
#endif // __OPENSPACE_CORE___DISTANCECONVERSION___H__
@@ -84,7 +84,7 @@
#ifdef WIN32
#define _USE_MATH_DEFINES
#endif // WIN32
#include <math.h>
#include <cmath>
namespace {
@@ -1218,8 +1218,9 @@ void AtmosphereDeferredcaster::executeCalculations(GLuint quadCalcVAO,
}
// Restores OpenGL blending state
if (blendEnabled)
if (blendEnabled) {
glEnable(GL_BLEND);
}
glBlendEquationSeparate(blendEquationRGB, blendEquationAlpha);
glBlendFuncSeparate(blendSrcRGB, blendDestRGB, blendSrcAlpha, blendDestAlpha);
@@ -186,7 +186,7 @@ private:
int _nu_samples;
glm::dmat4 _modelTransform;
double _time;
double _time = 0.0;
// Eclipse Shadows
std::vector<ShadowConfiguration> _shadowConfArray;
+2
View File
@@ -39,6 +39,7 @@ set(HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/lightsource/scenegraphlightsource.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/modelgeometry.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/multimodelgeometry.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderableboxgrid.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablecartesianaxes.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablemodel.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderableplane.h
@@ -82,6 +83,7 @@ set(SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/lightsource/scenegraphlightsource.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/modelgeometry.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/multimodelgeometry.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderableboxgrid.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablecartesianaxes.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablemodel.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderableplane.cpp
+3
View File
@@ -33,6 +33,7 @@
#include <modules/base/dashboard/dashboarditempropertyvalue.h>
#include <modules/base/dashboard/dashboarditemsimulationincrement.h>
#include <modules/base/dashboard/dashboarditemspacing.h>
#include <modules/base/rendering/renderableboxgrid.h>
#include <modules/base/dashboard/dashboarditemvelocity.h>
#include <modules/base/lightsource/cameralightsource.h>
#include <modules/base/lightsource/scenegraphlightsource.h>
@@ -117,6 +118,7 @@ void BaseModule::internalInitialize(const ghoul::Dictionary&) {
auto fRenderable = FactoryManager::ref().factory<Renderable>();
ghoul_assert(fRenderable, "Renderable factory was not created");
fRenderable->registerClass<RenderableBoxGrid>("RenderableBoxGrid");
fRenderable->registerClass<RenderableCartesianAxes>("RenderableCartesianAxes");
fRenderable->registerClass<RenderableModel>("RenderableModel");
fRenderable->registerClass<RenderablePlaneImageLocal>("RenderablePlaneImageLocal");
@@ -181,6 +183,7 @@ std::vector<documentation::Documentation> BaseModule::documentations() const {
DashboardItemSpacing::Documentation(),
DashboardItemVelocity::Documentation(),
RenderableBoxGrid::Documentation(),
RenderableModel::Documentation(),
RenderablePlane::Documentation(),
RenderableSphere::Documentation(),
@@ -61,8 +61,7 @@ documentation::Documentation CameraLightSource::Documentation() {
}
CameraLightSource::CameraLightSource()
: LightSource()
, _intensity(IntensityInfo, 1.f, 0.f, 1.f)
: _intensity(IntensityInfo, 1.f, 0.f, 1.f)
{
addProperty(_intensity);
}
@@ -76,8 +76,7 @@ documentation::Documentation SceneGraphLightSource::Documentation() {
}
SceneGraphLightSource::SceneGraphLightSource()
: LightSource()
, _intensity(IntensityInfo, 1.f, 0.f, 1.f)
: _intensity(IntensityInfo, 1.f, 0.f, 1.f)
, _sceneGraphNodeReference(NodeInfo, "")
{
addProperty(_intensity);
@@ -0,0 +1,320 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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/base/rendering/renderableboxgrid.h>
#include <modules/base/basemodule.h>
#include <openspace/engine/globals.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/util/spicemanager.h>
#include <openspace/util/updatestructures.h>
#include <openspace/documentation/verifier.h>
#include <ghoul/glm.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/opengl/programobject.h>
namespace {
constexpr const char* ProgramName = "GridProgram";
constexpr openspace::properties::Property::PropertyInfo GridColorInfo = {
"GridColor",
"Grid Color",
"This value determines the color of the grid lines that are rendered."
};
constexpr openspace::properties::Property::PropertyInfo GridMatrixInfo = {
"GridMatrix",
"Grid Matrix",
"This value specifies the local transformation matrix that defines the "
"orientation of this grid relative to the parent's rotation."
};
constexpr openspace::properties::Property::PropertyInfo SegmentsInfo = {
"Segments",
"Number of Segments",
"This value specifies the number of segments that are used to render the "
"surrounding sphere."
};
constexpr openspace::properties::Property::PropertyInfo LineWidthInfo = {
"LineWidth",
"Line Width",
"This value specifies the line width of the spherical grid."
};
constexpr openspace::properties::Property::PropertyInfo SizeInfo = {
"Size",
"Grid Size",
"This value species the size of each dimensions of the box"
};
} // namespace
namespace openspace {
documentation::Documentation RenderableBoxGrid::Documentation() {
using namespace documentation;
return {
"RenderableSphericalGrid",
"base_renderable_sphericalgrid",
{
{
GridMatrixInfo.identifier,
new DoubleMatrix4x4Verifier,
Optional::Yes,
GridMatrixInfo.description
},
{
GridColorInfo.identifier,
new DoubleVector4Verifier,
Optional::Yes,
GridColorInfo.description
},
{
SegmentsInfo.identifier,
new IntVerifier,
Optional::Yes,
SegmentsInfo.description
},
{
LineWidthInfo.identifier,
new DoubleVerifier,
Optional::Yes,
LineWidthInfo.description
},
{
SizeInfo.identifier,
new DoubleVector3Verifier,
Optional::Yes,
SizeInfo.description
}
}
};
}
RenderableBoxGrid::RenderableBoxGrid(const ghoul::Dictionary& dictionary)
: Renderable(dictionary)
, _gridMatrix(GridMatrixInfo, glm::mat4(1.f))
, _gridColor(
GridColorInfo,
glm::vec4(0.5f, 0.5, 0.5f, 1.f),
glm::vec4(0.f),
glm::vec4(1.f)
)
, _segments(SegmentsInfo, 36, 4, 200)
, _lineWidth(LineWidthInfo, 0.5f, 0.f, 20.f)
, _size(SizeInfo, glm::vec3(1e20f), glm::vec3(1.f), glm::vec3(1e35f))
{
documentation::testSpecificationAndThrow(
Documentation(),
dictionary,
"RenderableBoxGrid"
);
addProperty(_opacity);
registerUpdateRenderBinFromOpacity();
if (dictionary.hasKey(GridMatrixInfo.identifier)) {
_gridMatrix = dictionary.value<glm::dmat4>(GridMatrixInfo.identifier);
}
addProperty(_gridMatrix);
if (dictionary.hasKey(GridColorInfo.identifier)) {
_gridColor = dictionary.value<glm::vec4>(GridColorInfo.identifier);
}
_gridColor.setViewOption(properties::Property::ViewOptions::Color);
addProperty(_gridColor);
if (dictionary.hasKey(SegmentsInfo.identifier)) {
_segments = static_cast<int>(dictionary.value<double>(SegmentsInfo.identifier));
}
_segments.onChange([&]() { _gridIsDirty = true; });
addProperty(_segments);
if (dictionary.hasKey(LineWidthInfo.identifier)) {
_lineWidth = static_cast<float>(
dictionary.value<double>(LineWidthInfo.identifier)
);
}
addProperty(_lineWidth);
if (dictionary.hasKey(SizeInfo.identifier)) {
_size = dictionary.value<glm::vec3>(SizeInfo.identifier);
}
_size.onChange([&]() { _gridIsDirty = true; });
addProperty(_size);
}
bool RenderableBoxGrid::isReady() const {
return _gridProgram != nullptr;
}
void RenderableBoxGrid::initializeGL() {
_gridProgram = BaseModule::ProgramObjectManager.request(
ProgramName,
[]() -> std::unique_ptr<ghoul::opengl::ProgramObject> {
return global::renderEngine.buildRenderProgram(
ProgramName,
absPath("${MODULE_BASE}/shaders/grid_vs.glsl"),
absPath("${MODULE_BASE}/shaders/grid_fs.glsl")
);
}
);
glGenVertexArrays(1, &_vaoID);
glGenBuffers(1, &_vBufferID);
glBindVertexArray(_vaoID);
glBindBuffer(GL_ARRAY_BUFFER, _vBufferID);
glEnableVertexAttribArray(0);
glBindVertexArray(0);
}
void RenderableBoxGrid::deinitializeGL() {
glDeleteVertexArrays(1, &_vaoID);
_vaoID = 0;
glDeleteBuffers(1, &_vBufferID);
_vBufferID = 0;
BaseModule::ProgramObjectManager.release(
ProgramName,
[](ghoul::opengl::ProgramObject* p) {
global::renderEngine.removeRenderProgram(p);
}
);
_gridProgram = nullptr;
}
void RenderableBoxGrid::render(const RenderData& data, RendererTasks&){
_gridProgram->activate();
_gridProgram->setUniform("opacity", _opacity);
glm::dmat4 modelTransform =
glm::translate(glm::dmat4(1.0), data.modelTransform.translation) * // Translation
glm::dmat4(data.modelTransform.rotation) * // Spice rotation
glm::scale(glm::dmat4(1.0), glm::dvec3(data.modelTransform.scale));
glm::dmat4 modelViewTransform = data.camera.combinedViewMatrix() * modelTransform;
_gridProgram->setUniform("modelViewTransform", glm::mat4(modelViewTransform));
_gridProgram->setUniform("projectionTransform", data.camera.projectionMatrix());
_gridProgram->setUniform("gridColor", _gridColor);
glLineWidth(_lineWidth);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
glEnable(GL_LINE_SMOOTH);
glBindVertexArray(_vaoID);
glDrawArrays(_mode, 0, static_cast<GLsizei>(_varray.size()));
glBindVertexArray(0);
_gridProgram->deactivate();
}
void RenderableBoxGrid::update(const UpdateData&) {
if (_gridIsDirty) {
//_vsize = (_segments + 1) * (_segments + 1);
//_varray.resize(_vsize);
const glm::vec3 llf = -_size.value() / 2.f;
const glm::vec3 urb = _size.value() / 2.f;
// 7
// -------------------- 6
// / /
// /| /|
// 4 / | / |
// x-------------------x |
// | | |5 |
// | | | |
// | | | |
// | 3/----------------|--/ 2
// | / | /
// |/ |/
// x-------------------x
// 0 1
//
//
// For Line strip:
// 0 -> 1 -> 2 -> 3 -> 0 -> 4 -> 5 -> 6 -> 7 -> 4 -> 5(d) -> 1 -> 2(d) -> 6
// -> 7(d) -> 3
const glm::vec3 v0 = { llf.x, llf.y, llf.z };
const glm::vec3 v1 = { urb.x, llf.y, llf.z };
const glm::vec3 v2 = { urb.x, urb.y, llf.z };
const glm::vec3 v3 = { llf.x, urb.y, llf.z };
const glm::vec3 v4 = { llf.x, llf.y, urb.z };
const glm::vec3 v5 = { urb.x, llf.y, urb.z };
const glm::vec3 v6 = { urb.x, urb.y, urb.z };
const glm::vec3 v7 = { llf.x, urb.y, urb.z };
// First add the bounds
_varray.push_back({ v0.x, v0.y, v0.z });
_varray.push_back({ v1.x, v1.y, v1.z });
_varray.push_back({ v2.x, v2.y, v2.z });
_varray.push_back({ v3.x, v3.y, v3.z });
_varray.push_back({ v0.x, v0.y, v0.z });
_varray.push_back({ v4.x, v4.y, v4.z });
_varray.push_back({ v5.x, v5.y, v5.z });
_varray.push_back({ v6.x, v6.y, v6.z });
_varray.push_back({ v7.x, v7.y, v7.z });
_varray.push_back({ v4.x, v4.y, v4.z });
_varray.push_back({ v5.x, v5.y, v5.z });
_varray.push_back({ v1.x, v1.y, v1.z });
_varray.push_back({ v2.x, v2.y, v2.z });
_varray.push_back({ v6.x, v6.y, v6.z });
_varray.push_back({ v7.x, v7.y, v7.z });
_varray.push_back({ v3.x, v3.y, v3.z });
glBindVertexArray(_vaoID);
glBindBuffer(GL_ARRAY_BUFFER, _vBufferID);
glBufferData(
GL_ARRAY_BUFFER,
_varray.size() * sizeof(Vertex),
_varray.data(),
GL_STATIC_DRAW
);
glVertexAttribPointer(
0,
3,
GL_FLOAT,
GL_FALSE,
sizeof(Vertex),
nullptr // = reinterpret_cast<const GLvoid*>(offsetof(Vertex, location))
);
glBindVertexArray(0);
_gridIsDirty = false;
}
}
} // namespace openspace
@@ -0,0 +1,83 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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_BASE___RENDERABLEBOXGRID___H__
#define __OPENSPACE_MODULE_BASE___RENDERABLEBOXGRID___H__
#include <openspace/rendering/renderable.h>
#include <openspace/properties/stringproperty.h>
#include <openspace/properties/matrix/dmat4property.h>
#include <openspace/properties/scalar/intproperty.h>
#include <openspace/properties/vector/vec3property.h>
#include <openspace/properties/vector/vec4property.h>
#include <ghoul/opengl/ghoul_gl.h>
namespace ghoul::opengl {
class ProgramObject;
} // namespace ghoul::opengl
namespace openspace::documentation { struct Documentation; }
namespace openspace {
class RenderableBoxGrid : public Renderable {
public:
RenderableBoxGrid(const ghoul::Dictionary& dictionary);
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();
protected:
struct Vertex {
float location[3];
};
ghoul::opengl::ProgramObject* _gridProgram = nullptr;
properties::DMat4Property _gridMatrix;
properties::Vec4Property _gridColor;
properties::IntProperty _segments;
properties::FloatProperty _lineWidth;
properties::Vec3Property _size;
bool _gridIsDirty = true;
GLuint _vaoID = 0;
GLuint _vBufferID = 0;
GLenum _mode = GL_LINE_STRIP;
std::vector<Vertex> _varray;
};
}// namespace openspace
#endif // __OPENSPACE_MODULE_BASE___RENDERABLEBOXGRID___H__
@@ -240,8 +240,6 @@ RenderableModel::RenderableModel(const ghoul::Dictionary& dictionary)
addProperty(_performShading);
}
RenderableModel::~RenderableModel() {}
bool RenderableModel::isReady() const {
return _program && _texture;
}
+1 -1
View File
@@ -51,7 +51,7 @@ namespace modelgeometry { class ModelGeometry; }
class RenderableModel : public Renderable {
public:
RenderableModel(const ghoul::Dictionary& dictionary);
~RenderableModel();
~RenderableModel() = default;
void initialize() override;
void initializeGL() override;
@@ -57,7 +57,7 @@ private:
void loadTexture();
properties::StringProperty _texturePath;
ghoul::opengl::Texture* _texture;
ghoul::opengl::Texture* _texture = nullptr;
std::unique_ptr<ghoul::filesystem::File> _textureFile;
bool _textureIsDirty = false;
+41 -6
View File
@@ -217,6 +217,12 @@ documentation::Documentation FixedRotation::Documentation() {
Optional::Yes,
XAxisOrthogonalVectorInfo.description
},
{
XAxisInvertObjectInfo.identifier,
new BoolVerifier,
Optional::Yes,
XAxisInvertObjectInfo.description
},
{
KeyYAxis,
new OrVerifier({ new StringVerifier, new DoubleVector3Verifier, }),
@@ -234,6 +240,12 @@ documentation::Documentation FixedRotation::Documentation() {
Optional::Yes,
YAxisOrthogonalVectorInfo.description
},
{
YAxisInvertObjectInfo.identifier,
new BoolVerifier,
Optional::Yes,
YAxisInvertObjectInfo.description
},
{
KeyZAxis,
new OrVerifier({ new StringVerifier, new DoubleVector3Verifier, }),
@@ -251,6 +263,12 @@ documentation::Documentation FixedRotation::Documentation() {
Optional::Yes,
ZAxisOrthogonalVectorInfo.description
},
{
ZAxisInvertObjectInfo.identifier,
new BoolVerifier,
Optional::Yes,
ZAxisInvertObjectInfo.description
},
{
AttachedInfo.identifier,
new StringVerifier,
@@ -454,6 +472,11 @@ bool FixedRotation::initialize() {
if (_constructorDictionary.hasKey(KeyXAxisOrthogonal)) {
_xAxis.isOrthogonal = _constructorDictionary.value<bool>(KeyXAxisOrthogonal);
}
if (_constructorDictionary.hasKey(XAxisInvertObjectInfo.identifier)) {
_xAxis.invertObject = _constructorDictionary.value<bool>(
XAxisInvertObjectInfo.identifier
);
}
if (_xAxis.isOrthogonal) {
_xAxis.type = Axis::Type::OrthogonalVector;
}
@@ -474,6 +497,11 @@ bool FixedRotation::initialize() {
if (_constructorDictionary.hasKey(KeyYAxisOrthogonal)) {
_yAxis.isOrthogonal = _constructorDictionary.value<bool>(KeyYAxisOrthogonal);
}
if (_constructorDictionary.hasKey(YAxisInvertObjectInfo.identifier)) {
_yAxis.invertObject = _constructorDictionary.value<bool>(
YAxisInvertObjectInfo.identifier
);
}
if (_yAxis.isOrthogonal) {
_yAxis.type = Axis::Type::OrthogonalVector;
}
@@ -494,12 +522,16 @@ bool FixedRotation::initialize() {
if (_constructorDictionary.hasKey(KeyZAxisOrthogonal)) {
_zAxis.isOrthogonal = _constructorDictionary.value<bool>(KeyZAxisOrthogonal);
}
if (_constructorDictionary.hasKey(ZAxisInvertObjectInfo.identifier)) {
_yAxis.invertObject = _constructorDictionary.value<bool>(
ZAxisInvertObjectInfo.identifier
);
}
if (_zAxis.isOrthogonal) {
_zAxis.type = Axis::Type::OrthogonalVector;
}
if (!hasXAxis && hasYAxis && hasZAxis) {
_xAxis.type = Axis::Type::CoordinateSystemCompletion;
}
@@ -554,11 +586,14 @@ glm::vec3 FixedRotation::xAxis() const {
return glm::vec3(1.f, 0.f, 0.f);
case Axis::Type::Object:
if (_xAxis.node && _attachedNode) {
glm::vec3 dir = glm::vec3(glm::normalize(
_xAxis.node->worldPosition() -
_attachedNode->worldPosition()
));
return _xAxis.invertObject ? -dir : dir;
glm::dvec3 dir = _xAxis.node->worldPosition() -
_attachedNode->worldPosition();
if (dir == glm::dvec3(0.0)) {
dir = glm::dvec3(1.0, 0.0, 0.0);
}
glm::vec3 dirNorm = glm::vec3(glm::normalize(dir));
return _xAxis.invertObject ? -dirNorm : dirNorm;
}
else {
if (_xAxis.node) {
+1 -2
View File
@@ -114,8 +114,7 @@ TimeFrameInterval::TimeFrameInterval()
}
TimeFrameInterval::TimeFrameInterval(const ghoul::Dictionary& dictionary)
: TimeFrame()
, _hasStart(HasStartInfo, false)
: _hasStart(HasStartInfo, false)
, _start(StartInfo, 0, 0, 1E9)
, _hasEnd(HasEndInfo, false)
, _end(EndInfo, 0, 0, 1E9)
@@ -73,8 +73,6 @@ bool TimeFrameUnion::isActive(const Time& time) const {
return false;
}
TimeFrameUnion::TimeFrameUnion() {}
TimeFrameUnion::TimeFrameUnion(const ghoul::Dictionary& dictionary)
: TimeFrame()
{
+1 -1
View File
@@ -35,7 +35,7 @@ namespace documentation { struct Documentation; }
class TimeFrameUnion : public TimeFrame {
public:
TimeFrameUnion();
TimeFrameUnion() = default;
TimeFrameUnion(const ghoul::Dictionary& dictionary);
bool isActive(const Time&) const override;
+3 -3
View File
@@ -139,11 +139,11 @@ void CefWebGuiModule::internalInitialize(const ghoul::Dictionary& configuration)
_visible = configuration.hasValue<bool>(VisibleInfo.identifier) &&
configuration.value<bool>(VisibleInfo.identifier);
global::callback::initializeGL.push_back([this]() {
global::callback::initializeGL.emplace_back([this]() {
startOrStopGui();
});
global::callback::draw2D.push_back([this](){
global::callback::draw2D.emplace_back([this](){
const bool isGuiWindow =
global::windowDelegate.hasGuiWindow() ?
global::windowDelegate.isGuiWindow() :
@@ -160,7 +160,7 @@ void CefWebGuiModule::internalInitialize(const ghoul::Dictionary& configuration)
}
});
global::callback::deinitializeGL.push_back([this]() {
global::callback::deinitializeGL.emplace_back([this]() {
_enabled = false;
startOrStopGui();
});
+2 -2
View File
@@ -31,8 +31,8 @@ namespace openspace {
GUIKeyboardHandler::GUIKeyboardHandler() {
_keyConsumed = false;
global::callback::keyboard.push_back(
[&](Key key, KeyModifier mod, KeyAction action) -> bool {
global::callback::keyboard.emplace_back(
[&](Key, KeyModifier, KeyAction) -> bool {
const bool previous = _keyConsumed;
_keyConsumed = false;
return previous;
+1 -1
View File
@@ -57,7 +57,7 @@ GUIRenderHandler::GUIRenderHandler() {
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), 0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), nullptr);
glBindVertexArray(0);
LDEBUG("Initializing CEF GL environment... done!");
}
@@ -55,8 +55,6 @@ DebugRenderer::DebugRenderer(std::unique_ptr<ghoul::opengl::ProgramObject> progr
// nothing to do
}
DebugRenderer::~DebugRenderer() { }
const DebugRenderer& DebugRenderer::ref() {
if (!_reference) {
try {
@@ -70,7 +68,7 @@ const DebugRenderer& DebugRenderer::ref() {
}
void DebugRenderer::renderVertices(const Vertices& clippingSpacePoints, GLenum mode,
const glm::vec4& rgba) const
const glm::vec4& color) const
{
if (clippingSpacePoints.empty()) {
return;
@@ -88,7 +86,7 @@ void DebugRenderer::renderVertices(const Vertices& clippingSpacePoints, GLenum m
// Activate the shader program and set the uniform color within the shader
_programObject->activate();
_programObject->setUniform("color", rgba);
_programObject->setUniform("color", color);
glBindVertexArray(_vaoID);
glBindBuffer(GL_ARRAY_BUFFER, _vertexBufferID);
+1 -1
View File
@@ -61,7 +61,7 @@ public:
* Instantiate a new DebugRenderer with a custom shader program
*/
DebugRenderer(std::unique_ptr<ghoul::opengl::ProgramObject> programObject);
~DebugRenderer();
~DebugRenderer() = default;
/**
* Access the static reference
@@ -173,8 +173,6 @@ RenderableDebugPlane::RenderableDebugPlane(const ghoul::Dictionary& dictionary)
setBoundingSphere(_size);
}
RenderableDebugPlane::~RenderableDebugPlane() {}
bool RenderableDebugPlane::isReady() const {
bool ready = true;
if (!_shader) {
@@ -220,7 +218,7 @@ void RenderableDebugPlane::render(const RenderData& data, RendererTasks&) {
_shader->setUniform("ViewProjection", data.camera.viewProjectionMatrix());
_shader->setUniform("ModelTransform", transform);
setPscUniforms(*_shader.get(), data.camera, data.position);
setPscUniforms(*_shader, data.camera, data.position);
ghoul::opengl::TextureUnit unit;
unit.activate();
@@ -48,7 +48,7 @@ struct UpdateStructure;
class RenderableDebugPlane : public Renderable {
public:
RenderableDebugPlane(const ghoul::Dictionary& dictionary);
~RenderableDebugPlane();
~RenderableDebugPlane() = default;
void initializeGL() override;
void deinitializeGL() override;
@@ -47,7 +47,7 @@
#include <glm/gtx/string_cast.hpp>
#include <array>
#include <fstream>
#include <stdint.h>
#include <cstdint>
#include <locale>
#include <string>
@@ -423,8 +423,7 @@ RenderableBillboardsCloud::RenderableBillboardsCloud(const ghoul::Dictionary& di
if (dictionary.hasKey(KeyFile)) {
_speckFile = absPath(dictionary.value<std::string>(KeyFile));
_hasSpeckFile = true;
_drawElements.onChange([&]() {
_hasSpeckFile = _hasSpeckFile == true? false : true; });
_drawElements.onChange([&]() { _hasSpeckFile = !_hasSpeckFile; });
addProperty(_drawElements);
}
@@ -1163,7 +1162,7 @@ bool RenderableBillboardsCloud::readSpeckFile() {
// The beginning of the speck file has a header that either contains comments
// (signaled by a preceding '#') or information about the structure of the file
// (signaled by the keywords 'datavar', 'texturevar', and 'texture')
std::string line = "";
std::string line;
while (true) {
std::streampos position = file.tellg();
std::getline(file, line);
@@ -1253,7 +1252,7 @@ bool RenderableBillboardsCloud::readColorMapFile() {
// The beginning of the speck file has a header that either contains comments
// (signaled by a preceding '#') or information about the structure of the file
// (signaled by the keywords 'datavar', 'texturevar', and 'texture')
std::string line = "";
std::string line;
while (true) {
// std::streampos position = file.tellg();
std::getline(file, line);
@@ -1300,7 +1299,7 @@ bool RenderableBillboardsCloud::readLabelFile() {
// The beginning of the speck file has a header that either contains comments
// (signaled by a preceding '#') or information about the structure of the file
// (signaled by the keywords 'datavar', 'texturevar', and 'texture')
std::string line = "";
std::string line;
while (true) {
std::streampos position = file.tellg();
std::getline(file, line);
@@ -1375,7 +1374,7 @@ bool RenderableBillboardsCloud::readLabelFile() {
glm::vec3 transformedPos = glm::vec3(
_transformationMatrix * glm::dvec4(position, 1.0)
);
_labelData.push_back(std::make_pair(transformedPos, label));
_labelData.emplace_back(std::make_pair(transformedPos, label));
} while (!file.eof());
return true;
@@ -1411,12 +1410,10 @@ bool RenderableBillboardsCloud::loadCachedFile(const std::string& file) {
for (int i = 0; i < nItems; ++i) {
int32_t keySize = 0;
fileStream.read(reinterpret_cast<char*>(&keySize), sizeof(int32_t));
std::string key;
for (int c = 0; c < keySize; ++c) {
char t;
fileStream.read(&t, sizeof(char));
key.append(1, t);
}
std::vector<char> buffer(keySize);
fileStream.read(buffer.data(), keySize);
std::string key(buffer.begin(), buffer.end());
int32_t value = 0;
fileStream.read(reinterpret_cast<char*>(&value), sizeof(int32_t));
@@ -1461,23 +1458,21 @@ bool RenderableBillboardsCloud::saveCachedFile(const std::string& file) const {
int32_t nItems = static_cast<int32_t>(_variableDataPositionMap.size());
fileStream.write(reinterpret_cast<const char*>(&nItems), sizeof(int32_t));
for (auto pair : _variableDataPositionMap) {
for (const std::pair<const std::string, int>& pair :
_variableDataPositionMap)
{
int32_t keySize = static_cast<int32_t>(pair.first.size());
fileStream.write(
reinterpret_cast<const char*>(&keySize),
sizeof(int32_t)
);
for (size_t c = 0; c < pair.first.size(); ++c) {
char keyChar = static_cast<int32_t>(pair.first[c]);
fileStream.write(&keyChar, sizeof(char));
}
fileStream.write(pair.first.data(), keySize);
int32_t value = static_cast<int32_t>(pair.second);
fileStream.write(reinterpret_cast<const char*>(&value), sizeof(int32_t));
}
}
bool success = fileStream.good();
return success;
return fileStream.good();
}
else {
LERROR(fmt::format("Error opening file '{}' for save cache file", file));
@@ -1532,8 +1527,9 @@ void RenderableBillboardsCloud::createDataSlice() {
int c = static_cast<int>(colorBins.size() - 1);
while (variableColor < colorBins[c]) {
--c;
if (c == 0)
if (c == 0) {
break;
}
}
int colorIndex =
@@ -131,8 +131,8 @@ private:
// DEBUG:
properties::OptionProperty _renderOption;
ghoul::opengl::Texture* _polygonTexture;
ghoul::opengl::Texture* _spriteTexture;
ghoul::opengl::Texture* _polygonTexture = nullptr;
ghoul::opengl::Texture* _spriteTexture = nullptr;
ghoul::opengl::ProgramObject* _program = nullptr;
ghoul::opengl::ProgramObject* _renderToPolygonProgram = nullptr;
@@ -43,7 +43,7 @@
#include <ghoul/opengl/textureunit.h>
#include <array>
#include <fstream>
#include <stdint.h>
#include <cstdint>
namespace {
constexpr const char* _loggerCat = "RenderableDUMeshes";
@@ -268,8 +268,7 @@ RenderableDUMeshes::RenderableDUMeshes(const ghoul::Dictionary& dictionary)
if (dictionary.hasKey(KeyFile)) {
_speckFile = absPath(dictionary.value<std::string>(KeyFile));
_hasSpeckFile = true;
_drawElements.onChange([&]() {
_hasSpeckFile = _hasSpeckFile == true ? false : true; });
_drawElements.onChange([&]() { _hasSpeckFile = !_hasSpeckFile; });
addProperty(_drawElements);
}
@@ -706,7 +705,7 @@ bool RenderableDUMeshes::readSpeckFile() {
// The beginning of the speck file has a header that either contains comments
// (signaled by a preceding '#') or information about the structure of the file
// (signaled by the keywords 'datavar', 'texturevar', and 'texture')
std::string line = "";
std::string line;
while (true) {
std::streampos position = file.tellg();
std::getline(file, line);
@@ -827,7 +826,7 @@ bool RenderableDUMeshes::readLabelFile() {
// The beginning of the speck file has a header that either contains comments
// (signaled by a preceding '#') or information about the structure of the file
// (signaled by the keywords 'datavar', 'texturevar', and 'texture')
std::string line = "";
std::string line;
while (true) {
std::streampos position = file.tellg();
std::getline(file, line);
@@ -899,7 +898,7 @@ bool RenderableDUMeshes::readLabelFile() {
glm::vec3 transformedPos = glm::vec3(
_transformationMatrix * glm::dvec4(position, 1.0)
);
_labelData.push_back(std::make_pair(transformedPos, label));
_labelData.emplace_back(std::make_pair(transformedPos, label));
} while (!file.eof());
@@ -873,7 +873,7 @@ bool RenderablePlanesCloud::readSpeckFile() {
// The beginning of the speck file has a header that either contains comments
// (signaled by a preceding '#') or information about the structure of the file
// (signaled by the keywords 'datavar', 'texturevar', and 'texture')
std::string line = "";
std::string line;
while (true) {
std::streampos position = file.tellg();
std::getline(file, line);
@@ -950,7 +950,7 @@ bool RenderablePlanesCloud::readSpeckFile() {
if (line.substr(0, 8) == "texture ") {
std::stringstream str(line);
std::size_t found = line.find("-");
std::size_t found = line.find('-');
int textureIndex = 0;
@@ -1055,7 +1055,7 @@ bool RenderablePlanesCloud::readLabelFile() {
// The beginning of the speck file has a header that either contains comments
// (signaled by a preceding '#') or information about the structure of the file
// (signaled by the keywords 'datavar', 'texturevar', and 'texture')
std::string line = "";
std::string line;
while (true) {
std::streampos position = file.tellg();
std::getline(file, line);
@@ -1125,7 +1125,7 @@ bool RenderablePlanesCloud::readLabelFile() {
glm::vec3 transformedPos = glm::vec3(
_transformationMatrix * glm::dvec4(position, 1.0)
);
_labelData.push_back(std::make_pair(transformedPos, label));
_labelData.emplace_back(std::make_pair(transformedPos, label));
} while (!file.eof());
@@ -96,7 +96,7 @@ private:
const glm::dmat4& projectionMatrix, float fadeInVariable);
void renderLabels(const RenderData& data,
const glm::dmat4& modelViewProjectionMatrix, const glm::dvec3& orthoRight,
const glm::dvec3& orthoUp, float fadeInVarible);
const glm::dvec3& orthoUp, float fadeInVariable);
bool loadData();
bool loadTextures();
@@ -41,7 +41,7 @@
#include <array>
#include <fstream>
#include <locale>
#include <stdint.h>
#include <cstdint>
#include <string>
namespace {
@@ -406,7 +406,7 @@ void RenderablePoints::update(const UpdateData&) {
if (_hasSpriteTexture && _spriteTextureIsDirty) {
LDEBUG("Reloading Sprite Texture");
_spriteTexture = nullptr;
if (_spriteTexturePath.value() != "") {
if (!_spriteTexturePath.value().empty()) {
_spriteTexture = ghoul::io::TextureReader::ref().loadTexture(
absPath(_spriteTexturePath)
);
@@ -489,7 +489,7 @@ bool RenderablePoints::readSpeckFile() {
// The beginning of the speck file has a header that either contains comments
// (signaled by a preceding '#') or information about the structure of the file
// (signaled by the keywords 'datavar', 'texturevar', and 'texture')
std::string line = "";
std::string line;
while (true) {
std::streampos position = file.tellg();
std::getline(file, line);
@@ -556,7 +556,7 @@ bool RenderablePoints::readColorMapFile() {
// The beginning of the speck file has a header that either contains comments
// (signaled by a preceding '#') or information about the structure of the file
// (signaled by the keywords 'datavar', 'texturevar', and 'texture')
std::string line = "";
std::string line;
while (true) {
// std::streampos position = file.tellg();
std::getline(file, line);
+62
View File
@@ -0,0 +1,62 @@
##########################################################################################
# #
# OpenSpace #
# #
# Copyright (c) 2014-2018 #
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy of this #
# software and associated documentation files (the "Software"), to deal in the Software #
# without restriction, including without limitation the rights to use, copy, modify, #
# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to #
# permit persons to whom the Software is furnished to do so, subject to the following #
# conditions: #
# #
# The above copyright notice and this permission notice shall be included in all copies #
# or substantial portions of the Software. #
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, #
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A #
# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT #
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF #
# CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE #
# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #
##########################################################################################
include(${OPENSPACE_CMAKE_EXT_DIR}/module_definition.cmake)
include(${GHOUL_BASE_DIR}/support/cmake/handle_external_library.cmake)
set(HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/fitsfilereadermodule.h
${CMAKE_CURRENT_SOURCE_DIR}/include/fitsfilereader.h
)
source_group("Header Files" FILES ${HEADER_FILES})
set(SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/fitsfilereadermodule.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/fitsfilereader.cpp
)
source_group("Source Files" FILES ${SOURCE_FILES})
create_new_module(
"FitsFileReader"
fitsfilereader
${HEADER_FILES}
${SOURCE_FILES}
)
# Set root directories for external libraries.
set(CFITSIO_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ext/cfitsio/")
set(CCFITS_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ext/CCfits/")
set(INCLUDES_FOR_TARGET ${CCFITS_ROOT_DIR} "${CCFITS_ROOT_DIR}/../" ${CFITSIO_ROOT_DIR})
set(MODULE_NAME openspace-module-fitsfilereader)
# CCfits is dependent on cfitsio, let it handle the internal linking
add_subdirectory(${CFITSIO_ROOT_DIR})
set_folder_location(cfitsio "External")
add_subdirectory(${CCFITS_ROOT_DIR})
set_folder_location(CCfits "External")
TARGET_INCLUDE_DIRECTORIES(${MODULE_NAME} SYSTEM PUBLIC ${INCLUDES_FOR_TARGET})
TARGET_LINK_LIBRARIES(${MODULE_NAME} CCfits)
@@ -0,0 +1,31 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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/fitsfilereader/fitsfilereadermodule.h>
namespace openspace {
FitsFileReaderModule::FitsFileReaderModule() : OpenSpaceModule(Name) {}
} // namespace openspace
@@ -0,0 +1,41 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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_FITSFILEREADER___FITSFILEREADERMODULE___H__
#define __OPENSPACE_MODULE_FITSFILEREADER___FITSFILEREADERMODULE___H__
#include <openspace/util/openspacemodule.h>
namespace openspace {
class FitsFileReaderModule : public OpenSpaceModule {
public:
constexpr static const char* Name = "FitsFileReader";
FitsFileReaderModule();
};
} // namespace openspace
#endif // __OPENSPACE_MODULE_FITSFILEREADER___FITSFILEREADERMODULE___H__
@@ -0,0 +1,116 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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_FITSFILEREADER___FITSFILEREADER___H__
#define __OPENSPACE_MODULE_FITSFILEREADER___FITSFILEREADER___H__
#include <string>
#include <memory>
#include <mutex>
#include <unordered_map>
#include <valarray>
#include <vector>
namespace CCfits {
class FITS;
class PHDU;
class ExtHDU;
} // namespace CCfits
namespace ghoul::opengl { class Texture; }
namespace openspace {
template<typename T>
struct ImageData {
std::valarray<T> contents;
long int width;
long int height;
};
template<typename T>
struct TableData {
std::unordered_map<std::string, std::vector<T>> contents;
int readRows;
long int optimalRowsize;
std::string name;
};
class FitsFileReader {
public:
FitsFileReader(bool verboseMode);
~FitsFileReader();
template<typename T>
std::shared_ptr<ImageData<T>> readImage(const std::string& path);
template<typename T>
std::shared_ptr<std::unordered_map<std::string, T>> readHeader(
std::vector<std::string>& keywords);
template<typename T>
std::shared_ptr<T> readHeaderValue(const std::string key);
/**
* Read specified table columns from fits file.
* If <code>readAll</code> is set to true the entire table will be read before the
* selected columns, which makes the function take a lot longer if it's a big file.
* If no HDU index is given the current Extension HDU will be read from.
*/
template<typename T>
std::shared_ptr<TableData<T>> readTable(std::string& path,
const std::vector<std::string>& columnNames, int startRow = 1, int endRow = 10,
int hduIdx = 1, bool readAll = false);
/**
* Reads a single FITS file with pre-defined columns (defined for Viennas TGAS-file).
* Returns a vector with all read stars with <code>nValuesPerStar</code>.
* If additional columns are given by <code>filterColumnNames</code>, they will be
* read but it will slow doen the reading tremendously.
*/
std::vector<float> readFitsFile(std::string filePath, int& nValuesPerStar,
int firstRow, int lastRow, std::vector<std::string> filterColumnNames,
int multiplier = 1);
/**
* Reads a single SPECK file and returns a vector with <code>nRenderValues</code>
* per star. Reads data in pre-defined order based on AMNH's star data files.
*/
std::vector<float> readSpeckFile(const std::string& filePath, int& nRenderValues);
private:
std::unique_ptr<CCfits::FITS> _infile;
bool _verboseMode;
bool isPrimaryHDU();
template<typename T>
const std::shared_ptr<ImageData<T>> readImageInternal(CCfits::PHDU& image);
template<typename T>
const std::shared_ptr<ImageData<T>> readImageInternal(CCfits::ExtHDU& image);
mutable std::mutex _mutex;
};
} // namespace openspace
#endif // __OPENSPACE_MODULE_FITSFILEREADER___FITSFILEREADER___H__
@@ -0,0 +1,669 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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/fitsfilereader/include/fitsfilereader.h>
#include <openspace/util/distanceconversion.h>
#include <ghoul/fmt.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/misc/dictionary.h>
#include <CCfits>
#include <fstream>
using namespace CCfits;
namespace {
constexpr const char* _loggerCat = "FitsFileReader";
} // namespace
namespace openspace {
FitsFileReader::FitsFileReader(bool verboseMode) {
_verboseMode = verboseMode;
FITS::setVerboseMode(_verboseMode);
}
FitsFileReader::~FitsFileReader() {
if (_infile) {
_infile->destroy();
_infile = nullptr;
}
}
bool FitsFileReader::isPrimaryHDU() {
return _infile->extension().empty();
}
template <typename T>
std::shared_ptr<ImageData<T>> FitsFileReader::readImage(const std::string& path) {
try {
_infile = std::make_unique<FITS>(path, Read, true);
// Primary HDU Object
if (isPrimaryHDU()) {
return readImageInternal<T>(_infile->pHDU());
}
// Extension HDU Object
return readImageInternal<T>(_infile->currentExtension());
} catch (const FitsException& e){
LERROR("Could not read FITS image from table. " + e.message() );
}
return nullptr;
}
template <typename T>
std::shared_ptr<std::unordered_map<std::string, T>> FitsFileReader::readHeader(
std::vector<std::string>& keywords)
{
try {
HDU& image = isPrimaryHDU() ?
static_cast<HDU&>(_infile->pHDU()) :
static_cast<HDU&>(_infile->currentExtension());
std::vector<T> values;
image.readKeys(keywords, values);
if (values.size() != keywords.size()) {
LERROR("Number of keywords does not match number of values");
}
std::unordered_map<std::string, T> result;
std::transform(
keywords.begin(),
keywords.end(),
values.begin(),
std::inserter(
result,
result.end()
),
[](std::string key, T value) { return std::make_pair(key, value); }
);
return std::make_shared<std::unordered_map<std::string, T>>(std::move(result));
} catch (const FitsException& e) {
LERROR("Could not read FITS header. " + e.message() );
}
return nullptr;
}
template <typename T>
std::shared_ptr<T> FitsFileReader::readHeaderValue(const std::string key) {
try {
HDU& image = isPrimaryHDU() ?
static_cast<HDU&>(_infile->pHDU()) :
static_cast<HDU&>(_infile->currentExtension());
T value;
image.readKey(key, value);
return std::make_unique<T>(value);
} catch (FitsException& e) {
LERROR("Could not read FITS key. " + e.message() );
}
return nullptr;
}
template<typename T>
std::shared_ptr<TableData<T>> FitsFileReader::readTable(std::string& path,
const std::vector<std::string>& columnNames,
int startRow,
int endRow,
int hduIdx,
bool readAll)
{
// We need to lock reading when using multithreads because CCfits can't handle
// multiple I/O drivers.
std::lock_guard g(_mutex);
try {
_infile = std::make_unique<FITS>(path, Read, readAll);
// Make sure FITS file is not a Primary HDU Object (aka an image).
if (!isPrimaryHDU()) {
ExtHDU& table = _infile->extension(hduIdx);
int numCols = columnNames.size();
int numRowsInTable = table.rows();
std::unordered_map<string, std::vector<T>> contents;
//LINFO("Read file: " + _infile->name());
int firstRow = std::max(startRow, 1);
if (endRow < firstRow) {
endRow = numRowsInTable;
}
for (int i = 0; i < numCols; ++i) {
std::vector<T> columnData;
//LINFO("Read column: " + columnNames[i]);
table.column(columnNames[i]).read(columnData, firstRow, endRow);
contents[columnNames[i]] = columnData;
}
// Create TableData object of table contents.
TableData<T> loadedTable = {
std::move(contents),
static_cast<int>(table.rows()),
table.getRowsize(),
table.name()
};
return std::make_shared<TableData<T>>(loadedTable);
}
}
catch (FitsException& e) {
LERROR(fmt::format(
"Could not read FITS table from file '{}'. Make sure it's not an image file.",
e.message()
));
}
return nullptr;
}
std::vector<float> FitsFileReader::readFitsFile(std::string filePath, int& nValuesPerStar,
int firstRow, int lastRow,
std::vector<std::string> filterColumnNames,
int multiplier)
{
std::vector<float> fullData;
srand(1234567890);
if (firstRow <= 0) {
firstRow = 1;
}
// Define what columns to read.
std::vector<std::string> allColumnNames = {
"Position_X",
"Position_Y",
"Position_Z",
"Velocity_X",
"Velocity_Y",
"Velocity_Z",
"Gaia_Parallax",
"Gaia_G_Mag",
"Tycho_B_Mag",
"Tycho_V_Mag",
"Gaia_Parallax_Err",
"Gaia_Proper_Motion_RA",
"Gaia_Proper_Motion_RA_Err",
"Gaia_Proper_Motion_Dec",
"Gaia_Proper_Motion_Dec_Err",
"Tycho_B_Mag_Err",
"Tycho_V_Mag_Err"
};
// 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);
// Read columns from FITS file. If rows aren't specified then full table will be read.
std::shared_ptr<TableData<float>> table = readTable<float>(
filePath,
allColumnNames,
firstRow,
lastRow
);
if (!table) {
throw ghoul::RuntimeError(fmt::format("Failed to open Fits file '{}'", filePath));
}
int nStars = table->readRows - firstRow + 1;
int nNullArr = 0;
size_t nColumnsRead = allColumnNames.size();
size_t defaultCols = 17; // Number of columns that are copied by predefined code.
if (nColumnsRead != defaultCols) {
LINFO("Additional columns will be read! Consider add column in code for "
"significant speedup!");
}
// Declare how many values to save per star
nValuesPerStar = nColumnsRead + 1; // +1 for B-V color value.
// Copy columns to local variables.
std::unordered_map<std::string, std::vector<float>>& tableContent = table->contents;
// Default render parameters!
std::vector<float> posXcol = std::move(tableContent[allColumnNames[0]]);
std::vector<float> posYcol = std::move(tableContent[allColumnNames[1]]);
std::vector<float> posZcol = std::move(tableContent[allColumnNames[2]]);
std::vector<float> velXcol = std::move(tableContent[allColumnNames[3]]);
std::vector<float> velYcol = std::move(tableContent[allColumnNames[4]]);
std::vector<float> velZcol = std::move(tableContent[allColumnNames[5]]);
std::vector<float> parallax = std::move(tableContent[allColumnNames[6]]);
std::vector<float> magCol = std::move(tableContent[allColumnNames[7]]);
std::vector<float> tycho_b = std::move(tableContent[allColumnNames[8]]);
std::vector<float> tycho_v = std::move(tableContent[allColumnNames[9]]);
// Default filter parameters
// Additional filter parameters are handled as well but slows down reading
std::vector<float> parallax_err = std::move(tableContent[allColumnNames[10]]);
std::vector<float> pr_mot_ra = std::move(tableContent[allColumnNames[11]]);
std::vector<float> pr_mot_ra_err = std::move(tableContent[allColumnNames[12]]);
std::vector<float> pr_mot_dec = std::move(tableContent[allColumnNames[13]]);
std::vector<float> pr_mot_dec_err = std::move(tableContent[allColumnNames[14]]);
std::vector<float> tycho_b_err = std::move(tableContent[allColumnNames[15]]);
std::vector<float> tycho_v_err = std::move(tableContent[allColumnNames[16]]);
// Construct data array. OBS: ORDERING IS IMPORTANT! This is where slicing happens.
for (int i = 0; i < nStars * multiplier; ++i) {
std::vector<float> values(nValuesPerStar);
size_t idx = 0;
// Default order for rendering:
// Position [X, Y, Z]
// Absolute Magnitude
// B-V Color
// Velocity [X, Y, Z]
// Store positions.
values[idx++] = posXcol[i % nStars];
values[idx++] = posYcol[i % nStars];
values[idx++] = posZcol[i % nStars];
// Return early if star doesn't have a measured position.
if (values[0] == -999 && values[1] == -999 && values[2] == -999) {
nNullArr++;
continue;
}
// Store color values.
values[idx++] = magCol[i % nStars] == -999 ? 20.f : magCol[i % nStars];
values[idx++] = tycho_b[i % nStars] - tycho_v[i % nStars];
// Store velocity. Convert it to m/s with help by parallax.
values[idx++] = convertMasPerYearToMeterPerSecond(
velXcol[i % nStars],
parallax[i % nStars]
);
values[idx++] = convertMasPerYearToMeterPerSecond(
velYcol[i % nStars],
parallax[i % nStars]
);
values[idx++] = convertMasPerYearToMeterPerSecond(
velZcol[i % nStars],
parallax[i % nStars]
);
// Store additional parameters to filter by.
values[idx++] = parallax[i % nStars];
values[idx++] = parallax_err[i % nStars];
values[idx++] = pr_mot_ra[i % nStars];
values[idx++] = pr_mot_ra_err[i % nStars];
values[idx++] = pr_mot_dec[i % nStars];
values[idx++] = pr_mot_dec_err[i % nStars];
values[idx++] = tycho_b[i % nStars];
values[idx++] = tycho_b_err[i % nStars];
values[idx++] = tycho_v[i % nStars];
values[idx++] = tycho_v_err[i % nStars];
// Read extra columns, if any. This will slow down the sorting tremendously!
for (size_t col = defaultCols; col < nColumnsRead; ++col) {
std::vector<float> vecData = std::move(tableContent[allColumnNames[col]]);
values[idx++] = vecData[i];
}
for (size_t j = 0; j < nValuesPerStar; ++j) {
// The astronomers in Vienna use -999 as default value. Change it to 0.
if (values[j] == -999) {
values[j] = 0.f;
}
else if (multiplier > 1) {
values[j] *= static_cast<float>(rand()) / static_cast<float>(RAND_MAX);
}
}
fullData.insert(fullData.end(), values.begin(), values.end());
}
// Define what columns to read.
/*auto allColumnNames = std::vector<std::string>({
"ra",
"dec",
"parallax",
"pmra",
"pmdec",
"phot_g_mean_mag",
"phot_bp_mean_mag",
"phot_rp_mean_mag",
"radial_velocity",
});
// Append additional filter parameters to default rendering parameters.
allColumnNames.insert(allColumnNames.end(), filterColumnNames.begin(),
filterColumnNames.end());
std::string allNames = "Columns to read: \n";
for (auto colName : allColumnNames) {
allNames += colName + "\n";
}
LINFO(allNames);
// Read columns from FITS file. If rows aren't specified then full table will be read.
auto table = readTable<float>(filePath, allColumnNames, firstRow, lastRow);
if (!table) {
throw ghoul::RuntimeError(fmt::format("Failed to open Fits file '{}'", filePath));
}
int nStars = table->readRows - firstRow + 1;
int nNullArr = 0;
size_t nColumnsRead = allColumnNames.size();
size_t defaultCols = 9; // Number of columns that are copied by predefined code.
if (nColumnsRead != defaultCols) {
LINFO("Additional columns will be read! Consider add column in code for "
"significant speedup!");
}
// Declare how many values to save per star
nValuesPerStar = 8;
// Copy columns to local variables.
std::unordered_map<std::string, std::vector<float>>& tableContent = table->contents;
std::vector<float> ra = std::move(tableContent[allColumnNames[0]]);
std::vector<float> dec = std::move(tableContent[allColumnNames[1]]);
std::vector<float> parallax = std::move(tableContent[allColumnNames[2]]);
std::vector<float> pmra = std::move(tableContent[allColumnNames[3]]);
std::vector<float> pmdec = std::move(tableContent[allColumnNames[4]]);
std::vector<float> meanMagG = std::move(tableContent[allColumnNames[5]]);
std::vector<float> meanMagBp = std::move(tableContent[allColumnNames[6]]);
std::vector<float> meanMagRp = std::move(tableContent[allColumnNames[7]]);
std::vector<float> radial_vel = std::move(tableContent[allColumnNames[8]]);
// 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
// Bp-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
radiusInKiloParsec = 1.0 / 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
// 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(meanMagBp[i]) && std::isnan(meanMagRp[i]) ? 0.f
: meanMagBp[i] - meanMagRp[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.0 * 4.74 * radiusInKiloParsec * pmVecGal.x;
float tanVelY = 1000.0 * 4.74 * radiusInKiloParsec * pmVecGal.y;
float tanVelZ = 1000.0 * 4.74 * 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.0 * radial_vel[i] * rGal.x;
float radVelY = 1000.0 * radial_vel[i] * rGal.y;
float radVelZ = 1000.0 * 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]
}
fullData.insert(fullData.end(), values.begin(), values.end());
}*/
LINFO(fmt::format("{} out of {} read stars were null arrays", nNullArr, nStars));
LINFO(fmt::format("Multiplier: {}", multiplier));
return fullData;
}
std::vector<float> FitsFileReader::readSpeckFile(const std::string& filePath,
int& nRenderValues)
{
std::vector<float> fullData;
std::ifstream fileStream(filePath);
if (!fileStream.good()) {
LERROR(fmt::format("Failed to open Speck file '{}'", filePath));
return fullData;
}
int nValuesPerStar = 0;
int nNullArr = 0;
size_t nStars = 0;
// The beginning of the speck file has a header that either contains comments
// (signaled by a preceding '#') or information about the structure of the file
// (signaled by the keywords 'datavar', 'texturevar', 'texture' and 'maxcomment')
std::string line;
while (true) {
std::streampos position = fileStream.tellg();
std::getline(fileStream, line);
if (line[0] == '#' || line.empty()) {
continue;
}
if (line.substr(0, 7) != "datavar" && line.substr(0, 10) != "texturevar" &&
line.substr(0, 7) != "texture" && line.substr(0, 10) != "maxcomment")
{
// We read a line that doesn't belong to the header, so we have to jump back
// before the beginning of the current line.
fileStream.seekg(position);
break;
}
if (line.substr(0, 7) == "datavar") {
// datavar lines are structured as follows:
// datavar # description
// where # is the index of the data variable; so if we repeatedly overwrite
// the 'nValues' variable with the latest index, we will end up with the total
// number of values (+3 since X Y Z are not counted in the Speck file index)
std::stringstream str(line);
std::string dummy;
str >> dummy;
str >> nValuesPerStar;
nValuesPerStar += 1; // We want the number, but the index is 0 based
}
}
nValuesPerStar += 3; // X Y Z are not counted in the Speck file indices
// Order in DR1 file: DR2 - GaiaGroupMembers:
// 0 BVcolor 0 color
// 1 lum 1 lum
// 2 Vabsmag 2 absmag
// 3 Vappmag 3 Gmag
// 4 distly 4 distpc
// 5 distpcPctErr 5 plx
// 6 U 6 ra
// 7 V 7 dec
// 8 W 8 RadVel
// 9 speed 9 Teff
// 10 sptypeindex 10 vx
// 11 lumclassindex 11 vy
// 12 catsource 12 vz
// 13 texture 13 speed
// 14 texture
do {
std::vector<float> readValues(nValuesPerStar);
nStars++;
std::getline(fileStream, line);
std::stringstream str(line);
// Read values.
for (int i = 0; i < nValuesPerStar; ++i) {
str >> readValues[i];
}
// Check if star is a nullArray.
bool nullArray = true;
for (float f : readValues) {
if (f != 0.0) {
nullArray = false;
break;
}
}
// Insert to data if we found some values.
if (!nullArray) {
// Re-order data here because Octree expects the data in correct order when
// read.
// Default order for rendering:
// Position [X, Y, Z]
// Absolute Magnitude
// B-V Color
// Velocity [X, Y, Z]
nRenderValues = 8;
std::vector<float> renderValues(nRenderValues);
// Gaia DR1 data from AMNH measures positions in Parsec, but
// RenderableGaiaStars expects kiloParsec (because fits file from Vienna had
// in kPc).
// Thus we need to convert positions twice atm.
renderValues[0] = readValues[0] / 1000.0; // PosX
renderValues[1] = readValues[1] / 1000.0; // PosY
renderValues[2] = readValues[2] / 1000.0; // PosZ
renderValues[3] = readValues[6]; // AbsMag
renderValues[4] = readValues[3]; // color
renderValues[5] = readValues[13] * readValues[16]; // Vel X
renderValues[6] = readValues[14] * readValues[16]; // Vel Y
renderValues[7] = readValues[15] * readValues[16]; // Vel Z
fullData.insert(fullData.end(), renderValues.begin(), renderValues.end());
}
else {
nNullArr++;
}
} while (!fileStream.eof());
LINFO(fmt::format("{} out of {} read stars were null arrays", nNullArr, nStars));
return fullData;
}
// This is pretty annoying, the read method is not derived from the HDU class
// in CCfits - need to explicitly cast to the sub classes to access read
template<typename T>
const std::shared_ptr<ImageData<T>> FitsFileReader::readImageInternal(ExtHDU& image) {
try {
std::valarray<T> contents;
image.read(contents);
ImageData<T> im = { std::move(contents), image.axis(0), image.axis(1) };
return std::make_shared<ImageData<T>>(im);
} catch (const FitsException& e){
LERROR("Could not read FITS image EXTHDU. " + e.message() );
}
return nullptr;
}
template<typename T>
const std::shared_ptr<ImageData<T>> FitsFileReader::readImageInternal(PHDU& image) {
try {
std::valarray<T> contents;
image.read(contents);
ImageData<T> im = { std::move(contents), image.axis(0), image.axis(1) };
return std::make_shared<ImageData<T>>(im);
} catch (const FitsException& e){
LERROR("Could not read FITS image PHDU. " + e.message() );
}
return nullptr;
}
} // namespace openspace
+71
View File
@@ -0,0 +1,71 @@
##########################################################################################
# #
# OpenSpace #
# #
# Copyright (c) 2014-2018 #
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy of this #
# software and associated documentation files (the "Software"), to deal in the Software #
# without restriction, including without limitation the rights to use, copy, modify, #
# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to #
# permit persons to whom the Software is furnished to do so, subject to the following #
# conditions: #
# #
# The above copyright notice and this permission notice shall be included in all copies #
# or substantial portions of the Software. #
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, #
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A #
# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT #
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF #
# CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE #
# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #
##########################################################################################
include(${OPENSPACE_CMAKE_EXT_DIR}/module_definition.cmake)
set(HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/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}/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/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(
"Gaia"
gaia
STATIC
${HEADER_FILES} ${SOURCE_FILES} ${SHADER_FILES}
)
+72
View File
@@ -0,0 +1,72 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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/gaiamodule.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>
namespace openspace {
GaiaModule::GaiaModule() : OpenSpaceModule(Name) {}
void GaiaModule::internalInitialize(const ghoul::Dictionary&) {
auto fRenderable = FactoryManager::ref().factory<Renderable>();
ghoul_assert(fRenderable, "No renderable factory existed");
fRenderable->registerClass<RenderableGaiaStars>("RenderableGaiaStars");
auto fTask = FactoryManager::ref().factory<Task>();
ghoul_assert(fRenderable, "No task factory existed");
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
+50
View File
@@ -0,0 +1,50 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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___GAIAMODULE___H__
#define __OPENSPACE_MODULE_GAIA___GAIAMODULE___H__
#include <openspace/util/openspacemodule.h>
#include <openspace/documentation/documentation.h>
namespace openspace {
class GaiaModule : public OpenSpaceModule {
public:
constexpr static const char* Name = "Gaia";
GaiaModule();
virtual ~GaiaModule() = default;
std::vector<documentation::Documentation> documentations() const override;
scripting::LuaLibrary luaLibrary() const override;
private:
void internalInitialize(const ghoul::Dictionary&) override;
};
} // namespace openspace
#endif // __OPENSPACE_MODULE_GAIA___GAIAMODULE___H__
+6
View File
@@ -0,0 +1,6 @@
set(DEFAULT_MODULE ON)
set(OPENSPACE_DEPENDENCIES
fitsfilereader
globebrowsing
)
+54
View File
@@ -0,0 +1,54 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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___GAIAOPTIONS___H__
#define __OPENSPACE_MODULE_GAIA___GAIAOPTIONS___H__
namespace openspace::gaia {
enum RenderOption {
Static = 0,
Color = 1,
Motion = 2
};
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
};
} // namespace openspace::gaiamission
#endif // __OPENSPACE_MODULE_GAIA___GAIAOPTIONS___H__
+86
View File
@@ -0,0 +1,86 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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/rendering/octreeculler.h>
#include <ghoul/glm.h>
#include <ghoul/logging/logmanager.h>
namespace {
constexpr const char* _loggerCat = "OctreeCuller";
} // namespace
namespace openspace {
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);
}
void expand(globebrowsing::AABB3& bb, const glm::vec3& p) {
bb.min = glm::min(bb.min, p);
bb.max = glm::max(bb.max, p);
}
} // namespace
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);
}
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
+76
View File
@@ -0,0 +1,76 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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___OCTREECULLER___H__
#define __OPENSPACE_MODULE_GAIA___OCTREECULLER___H__
#include <modules/globebrowsing/src/basictypes.h>
#include <vector>
// TODO: Move /geometry/* to libOpenSpace so as not to depend on globebrowsing.
namespace openspace {
/**
* 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 OctreeCuller {
public:
/**
* \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);
~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:
/**
* 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_GAIA___OCTREECULLER___H__
File diff suppressed because it is too large Load Diff
+387
View File
@@ -0,0 +1,387 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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-2018 *
* *
* 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;
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__
+102
View File
@@ -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
+114
View File
@@ -0,0 +1,114 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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);
}
+132
View File
@@ -0,0 +1,132 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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-2018 *
* *
* 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;
}

Some files were not shown because too many files have changed in this diff Show More