mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-01-05 11:09:37 -06:00
Feature/new globe labels (#783)
Adding globe labels for planets https://github.com/OpenSpace/OpenSpace/issues/213
This commit is contained in:
committed by
Alexander Bock
parent
4b800ac819
commit
2b183b721b
@@ -1,6 +1,8 @@
|
||||
local transforms = asset.require('./transforms')
|
||||
local assetHelper = asset.require('util/asset_helper')
|
||||
local texturesPath = asset.require('./earth_textures').TexturesPath
|
||||
local labelsPath = asset.require('./earth_labels').LabelsPath
|
||||
|
||||
asset.request('./trail')
|
||||
|
||||
|
||||
@@ -266,7 +268,24 @@ local Earth = {
|
||||
Radius = 1.737E6
|
||||
}
|
||||
--Caster2 = { Name = "Independency Day Ship", Radius = 0.0, }
|
||||
}
|
||||
},
|
||||
Labels = {
|
||||
Enable = false,
|
||||
FileName = labelsPath .. "/Earth.labels",
|
||||
LabelAlignmentOption = "Horizontally", -- or Circularly
|
||||
LabelsFontSize = 41.0,
|
||||
LabelsSize = 0.52,
|
||||
LabelsMinSize = 1.0,
|
||||
LabelsMaxSize = 1500.0,
|
||||
ProximityEnabled = false,
|
||||
LabelsFadeInEnabled = true,
|
||||
LabelsFadeOutEnabled = false,
|
||||
FadeInStartingDistance = 50000.0,
|
||||
FadeOutStartingDistance = 80000.0,
|
||||
LabelsForceDomeRendering = true,
|
||||
LabelsDistanceEPS = 1500000.0,
|
||||
LabelsColor = {1.0, 0.0, 0.0, 1.0}
|
||||
}
|
||||
},
|
||||
Tag = { "planet_solarSystem", "planet_terrestrial" },
|
||||
GUI = {
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
local LabelsPath = asset.syncedResource({
|
||||
Name = "Earth Labels",
|
||||
Type = "HttpSynchronization",
|
||||
Identifier = "earth_labels",
|
||||
Version = 1
|
||||
})
|
||||
asset.export("LabelsPath", LabelsPath)
|
||||
@@ -1,5 +1,7 @@
|
||||
local assetHelper = asset.require('util/asset_helper')
|
||||
local transforms = asset.require('./transforms')
|
||||
local labelsPath = asset.require('./mercury_labels').LabelsPath
|
||||
|
||||
|
||||
asset.require("spice/base")
|
||||
asset.request('./trail')
|
||||
@@ -212,6 +214,21 @@ local Mercury = {
|
||||
SegmentsPerPatch = 64,
|
||||
Layers = {
|
||||
ColorLayers = color_layers
|
||||
},
|
||||
Labels = {
|
||||
Enable = false,
|
||||
FileName = labelsPath .. "/Mercury.labels",
|
||||
LabelAlignmentOption = "Horizontally", -- or Circularly
|
||||
LabelsFontSize = 40.0,
|
||||
LabelsSize = 10.0,
|
||||
LabelsMinSize = 1.0,
|
||||
LabelsMaxSize = 1500.0,
|
||||
ProximityEnabled = false,
|
||||
FadeInStartingDistance = 40000000.0,
|
||||
FadeOutStartingDistance = 80000.0,
|
||||
LabelsForceDomeRendering = true,
|
||||
LabelsDistanceEPS = 1500000.0,
|
||||
LabelsColor = {1.0, 1.0, 0.0, 1.0}
|
||||
}
|
||||
},
|
||||
Tag = { "planet_solarSystem", "planet_terrestrial" },
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
local LabelsPath = asset.syncedResource({
|
||||
Name = "Mercury Labels",
|
||||
Type = "HttpSynchronization",
|
||||
Identifier = "mercury_labels",
|
||||
Version = 1
|
||||
})
|
||||
asset.export("LabelsPath", LabelsPath)
|
||||
Submodule ext/ghoul updated: 5600165bb3...e3a388183c
@@ -852,6 +852,20 @@ void RenderableBillboardsCloud::renderLabels(const RenderData& data,
|
||||
glm::vec4 textColor = _textColor;
|
||||
textColor.a *= fadeInVariable;
|
||||
textColor.a *= _opacity;
|
||||
|
||||
ghoul::fontrendering::FontRenderer::ProjectedLabelsInformation labelInfo;
|
||||
labelInfo.orthoRight = orthoRight;
|
||||
labelInfo.orthoUp = orthoUp;
|
||||
labelInfo.minSize = static_cast<int>(_textMinSize);
|
||||
labelInfo.maxSize = static_cast<int>(_textMaxSize);
|
||||
labelInfo.cameraPos = data.camera.positionVec3();
|
||||
labelInfo.cameraLookUp = data.camera.lookUpVectorWorldSpace();
|
||||
labelInfo.renderType = _renderOption;
|
||||
labelInfo.mvpMatrix = modelViewProjectionMatrix;
|
||||
labelInfo.scale = pow(10.f, _textSize);
|
||||
labelInfo.enableDepth = true;
|
||||
labelInfo.enableFalseDepth = false;
|
||||
|
||||
for (const std::pair<glm::vec3, std::string>& pair : _labelData) {
|
||||
//glm::vec3 scaledPos(_transformationMatrix * glm::dvec4(pair.first, 1.0));
|
||||
glm::vec3 scaledPos(pair.first);
|
||||
@@ -861,15 +875,7 @@ void RenderableBillboardsCloud::renderLabels(const RenderData& data,
|
||||
scaledPos,
|
||||
pair.second,
|
||||
textColor,
|
||||
pow(10.f, _textSize.value()),
|
||||
static_cast<int>(_textMinSize),
|
||||
static_cast<int>(_textMaxSize),
|
||||
modelViewProjectionMatrix,
|
||||
orthoRight,
|
||||
orthoUp,
|
||||
data.camera.positionVec3(),
|
||||
data.camera.lookUpVectorWorldSpace(),
|
||||
_renderOption.value()
|
||||
labelInfo
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -552,6 +552,19 @@ void RenderableDUMeshes::renderLabels(const RenderData& data,
|
||||
break;
|
||||
}
|
||||
|
||||
ghoul::fontrendering::FontRenderer::ProjectedLabelsInformation labelInfo;
|
||||
labelInfo.orthoRight = orthoRight;
|
||||
labelInfo.orthoUp = orthoUp;
|
||||
labelInfo.minSize = static_cast<int>(_textMinSize);
|
||||
labelInfo.maxSize = static_cast<int>(_textMaxSize);
|
||||
labelInfo.cameraPos = data.camera.positionVec3();
|
||||
labelInfo.cameraLookUp = data.camera.lookUpVectorWorldSpace();
|
||||
labelInfo.renderType = _renderOption;
|
||||
labelInfo.mvpMatrix = modelViewProjectionMatrix;
|
||||
labelInfo.scale = pow(10.f, _textSize);
|
||||
labelInfo.enableDepth = true;
|
||||
labelInfo.enableFalseDepth = false;
|
||||
|
||||
for (const std::pair<glm::vec3, std::string>& pair : _labelData) {
|
||||
//glm::vec3 scaledPos(_transformationMatrix * glm::dvec4(pair.first, 1.0));
|
||||
glm::vec3 scaledPos(pair.first);
|
||||
@@ -561,15 +574,7 @@ void RenderableDUMeshes::renderLabels(const RenderData& data,
|
||||
scaledPos,
|
||||
pair.second,
|
||||
_textColor,
|
||||
pow(10.f, _textSize.value()),
|
||||
static_cast<int>(_textMinSize),
|
||||
static_cast<int>(_textMaxSize),
|
||||
modelViewProjectionMatrix,
|
||||
orthoRight,
|
||||
orthoUp,
|
||||
data.camera.positionVec3(),
|
||||
data.camera.lookUpVectorWorldSpace(),
|
||||
_renderOption.value()
|
||||
labelInfo
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -651,7 +651,21 @@ void RenderablePlanesCloud::renderLabels(const RenderData& data,
|
||||
}
|
||||
|
||||
glm::vec4 textColor = _textColor;
|
||||
textColor.a *= fadeInVariable;
|
||||
textColor.a *= fadeInVariable * _opacity;
|
||||
|
||||
ghoul::fontrendering::FontRenderer::ProjectedLabelsInformation labelInfo;
|
||||
labelInfo.orthoRight = orthoRight;
|
||||
labelInfo.orthoUp = orthoUp;
|
||||
labelInfo.minSize = static_cast<int>(_textMinSize);
|
||||
labelInfo.maxSize = static_cast<int>(_textMaxSize);
|
||||
labelInfo.cameraPos = data.camera.positionVec3();
|
||||
labelInfo.cameraLookUp = data.camera.lookUpVectorWorldSpace();
|
||||
labelInfo.renderType = _renderOption;
|
||||
labelInfo.mvpMatrix = modelViewProjectionMatrix;
|
||||
labelInfo.scale = pow(10.f, _textSize);
|
||||
labelInfo.enableDepth = true;
|
||||
labelInfo.enableFalseDepth = false;
|
||||
|
||||
for (const std::pair<glm::vec3, std::string>& pair : _labelData) {
|
||||
//glm::vec3 scaledPos(_transformationMatrix * glm::dvec4(pair.first, 1.0));
|
||||
glm::vec3 scaledPos(pair.first);
|
||||
@@ -661,15 +675,7 @@ void RenderablePlanesCloud::renderLabels(const RenderData& data,
|
||||
scaledPos,
|
||||
pair.second,
|
||||
textColor,
|
||||
pow(10.f, _textSize.value()),
|
||||
_textMinSize,
|
||||
_textMaxSize,
|
||||
modelViewProjectionMatrix,
|
||||
orthoRight,
|
||||
orthoUp,
|
||||
data.camera.positionVec3(),
|
||||
data.camera.lookUpVectorWorldSpace(),
|
||||
_renderOption.value()
|
||||
labelInfo
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,13 +26,13 @@ include(${OPENSPACE_CMAKE_EXT_DIR}/module_definition.cmake)
|
||||
|
||||
set(HEADER_FILES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/globebrowsingmodule.h
|
||||
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/asynctiledataprovider.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/basictypes.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/dashboarditemglobelocation.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/ellipsoid.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/gdalwrapper.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/geodeticpatch.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/globelabelscomponent.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/globetranslation.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/gpulayergroup.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/layer.h
|
||||
@@ -62,12 +62,12 @@ set(HEADER_FILES
|
||||
set(SOURCE_FILES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/globebrowsingmodule.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/globebrowsingmodule_lua.inl
|
||||
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/asynctiledataprovider.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/dashboarditemglobelocation.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/ellipsoid.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/gdalwrapper.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/geodeticpatch.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/globelabelscomponent.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/globetranslation.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/gpulayergroup.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/layer.cpp
|
||||
|
||||
849
modules/globebrowsing/src/globelabelscomponent.cpp
Normal file
849
modules/globebrowsing/src/globelabelscomponent.cpp
Normal file
@@ -0,0 +1,849 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2019 *
|
||||
* *
|
||||
* 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/globebrowsing/src/globelabelscomponent.h>
|
||||
|
||||
#include <modules/globebrowsing/globebrowsingmodule.h>
|
||||
#include <modules/globebrowsing/src/renderableglobe.h>
|
||||
#include <openspace/documentation/documentation.h>
|
||||
#include <openspace/documentation/verifier.h>
|
||||
#include <openspace/engine/openspaceengine.h>
|
||||
#include <openspace/engine/globals.h>
|
||||
#include <openspace/engine/moduleengine.h>
|
||||
#include <openspace/engine/windowdelegate.h>
|
||||
#include <openspace/util/updatestructures.h>
|
||||
#include <ghoul/filesystem/cachemanager.h>
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <ghoul/font/fontmanager.h>
|
||||
#include <ghoul/font/fontrenderer.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/misc/dictionary.h>
|
||||
#include <ghoul/opengl/programobject.h>
|
||||
#include <cstdlib>
|
||||
#include <fstream>
|
||||
#include <locale>
|
||||
|
||||
namespace {
|
||||
constexpr const char* keyLabels = "Labels";
|
||||
constexpr const char* keyLabelsFileName = "FileName";
|
||||
|
||||
constexpr const char* _loggerCat = "GlobeLabels";
|
||||
|
||||
constexpr int8_t CurrentCacheVersion = 1;
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo LabelsInfo = {
|
||||
"Labels",
|
||||
"Labels Enabled",
|
||||
"Enables and disables the rendering of labels on the globe surface from "
|
||||
"the csv label file"
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo LabelsEnableInfo = {
|
||||
"Enable",
|
||||
"Enable",
|
||||
"Enables and disables labels' rendering from the asset file."
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo LabelsFontSizeInfo = {
|
||||
"LabelsFontSize",
|
||||
"Labels Font Size",
|
||||
"Font size for the rendering labels. This is different fromt text size."
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo LabelsMaxSizeInfo = {
|
||||
"LabelsMaxSize",
|
||||
"Labels Maximum Text Size",
|
||||
"Maximum label size"
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo LabelsMinSizeInfo = {
|
||||
"LabelsMinSize",
|
||||
"Labels Minimum Text Size",
|
||||
"Minimum label size"
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo LabelsSizeInfo = {
|
||||
"LabelsSize",
|
||||
"Labels Size",
|
||||
"Labels Size"
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo LabelsMinHeightInfo = {
|
||||
"LabelsMinHeight",
|
||||
"Labels Minimum Height",
|
||||
"Labels Minimum Height"
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo LabelsColorInfo = {
|
||||
"LabelsColor",
|
||||
"Labels Color",
|
||||
"Labels Color"
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo
|
||||
LabelsFadeInStartingDistanceInfo =
|
||||
{
|
||||
"FadeInStartingDistance",
|
||||
"Fade In Starting Distance for Labels",
|
||||
"Fade In Starting Distance for Labels"
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo
|
||||
LabelsFadeOutStartingDistanceInfo =
|
||||
{
|
||||
"FadeOutStartingDistance",
|
||||
"Fade Out Starting Distance for Labels",
|
||||
"Fade Out Starting Distance for Labels"
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo
|
||||
LabelsFadeInEnabledInfo =
|
||||
{
|
||||
"LabelsFadeInEnabled",
|
||||
"Labels fade In enabled",
|
||||
"Labels fade In enabled"
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo
|
||||
LabelsFadeOutEnabledInfo =
|
||||
{
|
||||
"LabelsFadeOutEnabled",
|
||||
"Labels fade Out enabled",
|
||||
"Labels fade Out enabled"
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo
|
||||
LabelsDisableCullingEnabledInfo =
|
||||
{
|
||||
"LabelsDisableCullingEnabled",
|
||||
"Labels culling disabled",
|
||||
"Labels culling disabled"
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo LabelsDistanceEPSInfo = {
|
||||
"LabelsDistanceEPS",
|
||||
"Labels culling distance from globe's center",
|
||||
"Labels culling distance from globe's center"
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo LabelAlignmentOptionInfo = {
|
||||
"LabelAlignmentOption",
|
||||
"Label Alignment Option",
|
||||
"Labels are aligned horizontally or circularly related to the planet."
|
||||
};
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation GlobeLabelsComponent::Documentation() {
|
||||
using namespace documentation;
|
||||
return {
|
||||
"GlobeLabels Component",
|
||||
"globebrowsing_globelabelscomponent",
|
||||
{
|
||||
{
|
||||
LabelsInfo.identifier,
|
||||
new BoolVerifier,
|
||||
Optional::Yes,
|
||||
LabelsInfo.description
|
||||
},
|
||||
{
|
||||
LabelsEnableInfo.identifier,
|
||||
new BoolVerifier,
|
||||
Optional::Yes,
|
||||
LabelsEnableInfo.description
|
||||
},
|
||||
{
|
||||
LabelsFontSizeInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
LabelsFontSizeInfo.description
|
||||
},
|
||||
{
|
||||
LabelsMaxSizeInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
LabelsMaxSizeInfo.description
|
||||
},
|
||||
{
|
||||
LabelsMinSizeInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
LabelsMinSizeInfo.description
|
||||
},
|
||||
{
|
||||
LabelsSizeInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
LabelsSizeInfo.description
|
||||
},
|
||||
{
|
||||
LabelsMinHeightInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
LabelsMinHeightInfo.description
|
||||
},
|
||||
{
|
||||
LabelsColorInfo.identifier,
|
||||
new Vector4Verifier<float>(),
|
||||
Optional::Yes,
|
||||
LabelsColorInfo.description
|
||||
},
|
||||
{
|
||||
LabelsFadeInStartingDistanceInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
LabelsFadeInStartingDistanceInfo.description
|
||||
},
|
||||
{
|
||||
LabelsFadeOutStartingDistanceInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
LabelsFadeOutStartingDistanceInfo.description
|
||||
},
|
||||
{
|
||||
LabelsFadeInEnabledInfo.identifier,
|
||||
new BoolVerifier,
|
||||
Optional::Yes,
|
||||
LabelsFadeInEnabledInfo.description
|
||||
},
|
||||
{
|
||||
LabelsFadeOutEnabledInfo.identifier,
|
||||
new BoolVerifier,
|
||||
Optional::Yes,
|
||||
LabelsFadeOutEnabledInfo.description
|
||||
},
|
||||
{
|
||||
LabelsDisableCullingEnabledInfo.identifier,
|
||||
new BoolVerifier,
|
||||
Optional::Yes,
|
||||
LabelsDisableCullingEnabledInfo.description
|
||||
},
|
||||
{
|
||||
LabelsDistanceEPSInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
LabelsDistanceEPSInfo.description
|
||||
},
|
||||
{
|
||||
LabelAlignmentOptionInfo.identifier,
|
||||
new StringVerifier,
|
||||
Optional::Yes,
|
||||
LabelAlignmentOptionInfo.description
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
GlobeLabelsComponent::GlobeLabelsComponent()
|
||||
: properties::PropertyOwner({ "Labels" })
|
||||
, _labelsEnabled(LabelsInfo, false)
|
||||
, _labelsFontSize(LabelsFontSizeInfo, 30, 1, 300)
|
||||
, _labelsMaxSize(LabelsMaxSizeInfo, 300, 10, 1000)
|
||||
, _labelsMinSize(LabelsMinSizeInfo, 4, 1, 100)
|
||||
, _labelsSize(LabelsSizeInfo, 2.5, 0, 30)
|
||||
, _labelsMinHeight(LabelsMinHeightInfo, 100.0, 0.0, 10000.0)
|
||||
, _labelsColor(LabelsColorInfo, glm::vec4(1.f, 1.f, 0.f, 1.f),
|
||||
glm::vec4(0.f), glm::vec4(1.f))
|
||||
, _labelsFadeInDist(LabelsFadeInStartingDistanceInfo, 1E6, 1E3, 1E8)
|
||||
, _labelsFadeOutDist(LabelsFadeOutStartingDistanceInfo, 1E4, 1, 1E7)
|
||||
, _labelsFadeInEnabled(LabelsFadeInEnabledInfo, false)
|
||||
, _labelsFadeOutEnabled(LabelsFadeOutEnabledInfo, false)
|
||||
, _labelsDisableCullingEnabled(LabelsDisableCullingEnabledInfo, false)
|
||||
, _labelsDistaneEPS(LabelsDistanceEPSInfo, 100000.f, 1000.f, 10000000.f)
|
||||
, _labelAlignmentOption(
|
||||
LabelAlignmentOptionInfo,
|
||||
properties::OptionProperty::DisplayType::Dropdown
|
||||
)
|
||||
{
|
||||
addProperty(_labelsEnabled);
|
||||
addProperty(_labelsFontSize);
|
||||
addProperty(_labelsSize);
|
||||
addProperty(_labelsMinHeight);
|
||||
_labelsColor.setViewOption(properties::Property::ViewOptions::Color);
|
||||
addProperty(_labelsColor);
|
||||
addProperty(_labelsFadeInDist);
|
||||
addProperty(_labelsFadeOutDist);
|
||||
addProperty(_labelsMinSize);
|
||||
addProperty(_labelsFadeInEnabled);
|
||||
addProperty(_labelsFadeOutEnabled);
|
||||
addProperty(_labelsDisableCullingEnabled);
|
||||
addProperty(_labelsDistaneEPS);
|
||||
|
||||
_labelAlignmentOption.addOption(0, "Horizontally");
|
||||
_labelAlignmentOption.addOption(1, "Circularly");
|
||||
_labelAlignmentOption = Horizontally;
|
||||
addProperty(_labelAlignmentOption);
|
||||
}
|
||||
|
||||
void GlobeLabelsComponent::initialize(const ghoul::Dictionary& dictionary,
|
||||
globebrowsing::RenderableGlobe* globe)
|
||||
{
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
dictionary,
|
||||
"GlobeLabelsComponent"
|
||||
);
|
||||
|
||||
_globe = globe;
|
||||
|
||||
// Reads labels' file and build cache file if necessary
|
||||
if (dictionary.empty()) {
|
||||
return;
|
||||
}
|
||||
std::string labelsFile;
|
||||
bool successLabels = dictionary.getValue(keyLabelsFileName, labelsFile);
|
||||
if (!successLabels) {
|
||||
return;
|
||||
}
|
||||
bool loadSuccess = loadLabelsData(absPath(labelsFile));
|
||||
if (!loadSuccess) {
|
||||
return;
|
||||
}
|
||||
if (dictionary.hasKey(LabelsEnableInfo.identifier)) {
|
||||
// In case of the label's dic is present but is disabled
|
||||
_labelsEnabled = dictionary.value<bool>(LabelsEnableInfo.identifier);
|
||||
}
|
||||
else {
|
||||
// Is the labels dic is enable in the configuration file,
|
||||
// enables the label automatically.
|
||||
_labelsEnabled = true;
|
||||
}
|
||||
|
||||
if (dictionary.hasKey(LabelsFontSizeInfo.identifier)) {
|
||||
float fontSize = dictionary.value<float>(LabelsFontSizeInfo.identifier);
|
||||
_labelsFontSize = fontSize;
|
||||
_labelsFontSize.onChange([this]() { initializeFonts(); });
|
||||
}
|
||||
|
||||
if (dictionary.hasKey(LabelsSizeInfo.identifier)) {
|
||||
_labelsSize = static_cast<float>(
|
||||
dictionary.value<double>(LabelsSizeInfo.identifier)
|
||||
);
|
||||
}
|
||||
|
||||
if (dictionary.hasKey(LabelsMinHeightInfo.identifier)) {
|
||||
_labelsMinHeight = dictionary.value<float>(LabelsMinHeightInfo.identifier);
|
||||
}
|
||||
|
||||
if (dictionary.hasKey(LabelsColorInfo.identifier)) {
|
||||
_labelsColor = dictionary.value<glm::vec4>(LabelsColorInfo.identifier);
|
||||
}
|
||||
|
||||
if (dictionary.hasKey(LabelsFadeInEnabledInfo.identifier)) {
|
||||
_labelsFadeInEnabled = dictionary.value<bool>(LabelsFadeInEnabledInfo.identifier);
|
||||
}
|
||||
|
||||
if (dictionary.hasKey(LabelsFadeInStartingDistanceInfo.identifier)) {
|
||||
_labelsFadeInDist = dictionary.value<float>(
|
||||
LabelsFadeInStartingDistanceInfo.identifier
|
||||
);
|
||||
}
|
||||
|
||||
if (dictionary.hasKey(LabelsFadeOutEnabledInfo.identifier)) {
|
||||
_labelsFadeOutEnabled = dictionary.value<bool>(
|
||||
LabelsFadeOutEnabledInfo.identifier
|
||||
);
|
||||
}
|
||||
|
||||
if (dictionary.hasKey(LabelsFadeOutStartingDistanceInfo.identifier)) {
|
||||
_labelsFadeOutDist = dictionary.value<float>(
|
||||
LabelsFadeOutStartingDistanceInfo.identifier
|
||||
);
|
||||
}
|
||||
|
||||
if (dictionary.hasKey(LabelsMinSizeInfo.identifier)) {
|
||||
_labelsMinSize = static_cast<int>(
|
||||
dictionary.value<float>(LabelsMinSizeInfo.identifier)
|
||||
);
|
||||
}
|
||||
|
||||
if (dictionary.hasKey(LabelsMaxSizeInfo.identifier)) {
|
||||
_labelsMaxSize = static_cast<int>(
|
||||
dictionary.value<float>(LabelsMaxSizeInfo.identifier)
|
||||
);
|
||||
}
|
||||
|
||||
if (dictionary.hasKey(LabelsDisableCullingEnabledInfo.identifier)) {
|
||||
bool disabled = dictionary.value<bool>(
|
||||
LabelsDisableCullingEnabledInfo.identifier
|
||||
);
|
||||
_labelsDisableCullingEnabled.set(disabled);
|
||||
}
|
||||
|
||||
if (dictionary.hasKey(LabelsDistanceEPSInfo.identifier)) {
|
||||
_labelsDistaneEPS = static_cast<float>(
|
||||
dictionary.value<double>(LabelsDistanceEPSInfo.identifier)
|
||||
);
|
||||
}
|
||||
|
||||
if (dictionary.hasKey(LabelAlignmentOptionInfo.identifier)) {
|
||||
std::string alignment =
|
||||
dictionary.value<std::string>(LabelAlignmentOptionInfo.identifier);
|
||||
if (alignment == "Horizontally") {
|
||||
_labelAlignmentOption = Horizontally;
|
||||
}
|
||||
else {
|
||||
_labelAlignmentOption = Circularly;
|
||||
}
|
||||
}
|
||||
|
||||
initializeFonts();
|
||||
}
|
||||
|
||||
void GlobeLabelsComponent::initializeFonts() {
|
||||
_font = openspace::global::fontManager.font(
|
||||
"Mono",
|
||||
static_cast<float>(_labelsFontSize),
|
||||
ghoul::fontrendering::FontManager::Outline::Yes,
|
||||
ghoul::fontrendering::FontManager::LoadGlyphs::No
|
||||
);
|
||||
}
|
||||
|
||||
bool GlobeLabelsComponent::loadLabelsData(const std::string& file) {
|
||||
std::string cachedFile = FileSys.cacheManager()->cachedFilename(
|
||||
ghoul::filesystem::File(file),
|
||||
"GlobeLabelsComponent|" + identifier(),
|
||||
ghoul::filesystem::CacheManager::Persistent::Yes
|
||||
);
|
||||
|
||||
bool hasCachedFile = FileSys.fileExists(cachedFile);
|
||||
if (hasCachedFile) {
|
||||
LINFO(fmt::format("Cached file '{}' used for labels file: {}", cachedFile, file));
|
||||
|
||||
const bool hasCache = loadCachedFile(cachedFile);
|
||||
if (hasCache) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
FileSys.cacheManager()->removeCacheFile(file);
|
||||
// Intentional fall-through to the 'else' to generate the cache
|
||||
// file for the next run
|
||||
}
|
||||
}
|
||||
else {
|
||||
LINFO(fmt::format("Cache for labels file '{}' not found", file));
|
||||
}
|
||||
LINFO(fmt::format("Loading labels file '{}'", file));
|
||||
|
||||
bool success = readLabelsFile(file);
|
||||
if (success) {
|
||||
saveCachedFile(cachedFile);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool GlobeLabelsComponent::readLabelsFile(const std::string& file) {
|
||||
try {
|
||||
std::fstream csvLabelFile(file);
|
||||
if (!csvLabelFile.good()) {
|
||||
LERROR(fmt::format("Failed to open labels file '{}'", file));
|
||||
return false;
|
||||
}
|
||||
if (!csvLabelFile.is_open()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
_labels.labelsArray.clear();
|
||||
|
||||
std::string sline;
|
||||
while (!csvLabelFile.eof()) {
|
||||
std::getline(csvLabelFile, sline);
|
||||
if (sline.size() <= 10) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::istringstream iss(sline);
|
||||
std::string token;
|
||||
std::getline(iss, token, ',');
|
||||
|
||||
// First line is just the Header
|
||||
if (token == "Feature_Name") {
|
||||
continue;
|
||||
}
|
||||
|
||||
LabelEntry lEntry;
|
||||
|
||||
// Non-ascii characters aren't displayed correctly by the text
|
||||
// rendering (We don't have the non-ascii character in the texture
|
||||
// atlas)
|
||||
// Once this limitation is fixed, we can remove the next piece of code
|
||||
// Removing non ASCII characters:
|
||||
strncpy(lEntry.feature, token.c_str(), 256);
|
||||
int tokenChar = 0;
|
||||
while (tokenChar < 256) {
|
||||
if ((lEntry.feature[tokenChar] < 0 || lEntry.feature[tokenChar] > 127) &&
|
||||
lEntry.feature[tokenChar] != '\0')
|
||||
{
|
||||
lEntry.feature[tokenChar] = '*';
|
||||
}
|
||||
else if (lEntry.feature[tokenChar] == '\"') {
|
||||
lEntry.feature[tokenChar] = '=';
|
||||
}
|
||||
tokenChar++;
|
||||
}
|
||||
|
||||
std::getline(iss, token, ','); // Target is not used
|
||||
|
||||
std::getline(iss, token, ','); // Diameter
|
||||
lEntry.diameter = std::stof(token);
|
||||
|
||||
std::getline(iss, token, ','); // Latitude
|
||||
lEntry.latitude = std::stof(token);
|
||||
|
||||
std::getline(iss, token, ','); // Longitude
|
||||
lEntry.longitude = std::stof(token);
|
||||
|
||||
std::getline(iss, token, ','); // Coord System
|
||||
std::string coordinateSystem(token);
|
||||
std::size_t found = coordinateSystem.find("West");
|
||||
if (found != std::string::npos) {
|
||||
lEntry.longitude = 360.0f - lEntry.longitude;
|
||||
}
|
||||
|
||||
// Clean white spaces
|
||||
std::istringstream issFeature(lEntry.feature);
|
||||
std::getline(issFeature, token, '=');
|
||||
if (token == "")
|
||||
std::getline(issFeature, token, '=');
|
||||
strncpy(lEntry.feature, token.c_str(), 256);
|
||||
|
||||
GlobeBrowsingModule* _globeBrowsingModule =
|
||||
global::moduleEngine.module<openspace::GlobeBrowsingModule>();
|
||||
lEntry.geoPosition = _globeBrowsingModule->cartesianCoordinatesFromGeo(
|
||||
*_globe,
|
||||
lEntry.latitude,
|
||||
lEntry.longitude,
|
||||
lEntry.diameter
|
||||
);
|
||||
|
||||
_labels.labelsArray.push_back(lEntry);
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (const std::fstream::failure& e) {
|
||||
LERROR(fmt::format("Failed reading labels file '{}'", file));
|
||||
LERROR(e.what());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool GlobeLabelsComponent::loadCachedFile(const std::string& file) {
|
||||
std::ifstream fileStream(file, std::ifstream::binary);
|
||||
if (!fileStream.good()) {
|
||||
LERROR(fmt::format("Error opening file '{}' for loading cache file", file));
|
||||
return false;
|
||||
}
|
||||
|
||||
int8_t version = 0;
|
||||
fileStream.read(reinterpret_cast<char*>(&version), sizeof(int8_t));
|
||||
if (version != CurrentCacheVersion) {
|
||||
LINFO("The format of the cached file has changed: deleting old cache");
|
||||
fileStream.close();
|
||||
FileSys.deleteFile(file);
|
||||
return false;
|
||||
}
|
||||
|
||||
int32_t nValues = 0;
|
||||
fileStream.read(reinterpret_cast<char*>(&nValues), sizeof(int32_t));
|
||||
_labels.labelsArray.resize(nValues);
|
||||
|
||||
fileStream.read(
|
||||
reinterpret_cast<char*>(_labels.labelsArray.data()),
|
||||
nValues * sizeof(_labels.labelsArray[0])
|
||||
);
|
||||
|
||||
return fileStream.good();
|
||||
}
|
||||
|
||||
bool GlobeLabelsComponent::saveCachedFile(const std::string& file) const {
|
||||
std::ofstream fileStream(file, std::ofstream::binary);
|
||||
if (!fileStream.good()) {
|
||||
LERROR(fmt::format("Error opening file '{}' for save cache file", file));
|
||||
return false;
|
||||
}
|
||||
fileStream.write(reinterpret_cast<const char*>(&CurrentCacheVersion),
|
||||
sizeof(int8_t));
|
||||
|
||||
int32_t nValues = static_cast<int32_t>(_labels.labelsArray.size());
|
||||
if (nValues == 0) {
|
||||
LERROR("Error writing cache: No values were loaded");
|
||||
return false;
|
||||
}
|
||||
fileStream.write(reinterpret_cast<const char*>(&nValues), sizeof(int32_t));
|
||||
|
||||
size_t nBytes = nValues * sizeof(_labels.labelsArray[0]);
|
||||
fileStream.write(reinterpret_cast<const char*>(&_labels.labelsArray[0]), nBytes);
|
||||
|
||||
return fileStream.good();
|
||||
}
|
||||
|
||||
void GlobeLabelsComponent::draw(const RenderData& data) {
|
||||
if (!_labelsEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate the MVP matrix
|
||||
glm::dmat4 viewTransform = glm::dmat4(data.camera.combinedViewMatrix());
|
||||
glm::dmat4 vp = glm::dmat4(data.camera.sgctInternal.projectionMatrix()) *
|
||||
viewTransform;
|
||||
glm::dmat4 mvp = vp * _globe->modelTransform();
|
||||
|
||||
glm::dvec3 globePositionWorld = glm::dvec3(_globe->modelTransform() *
|
||||
glm::vec4(0.f, 0.f, 0.f, 1.f));
|
||||
glm::dvec3 cameraToGlobeDistanceWorld = globePositionWorld -
|
||||
data.camera.positionVec3();
|
||||
double distanceCameraGlobeWorld = glm::length(cameraToGlobeDistanceWorld);
|
||||
|
||||
float varyingOpacity = 1.f;
|
||||
if (_labelsFadeInEnabled) {
|
||||
double averageRadius = (
|
||||
_globe->ellipsoid().radii().x + _globe->ellipsoid().radii().y +
|
||||
_globe->ellipsoid().radii().z
|
||||
) / 3.0;
|
||||
glm::dvec2 fadeRange = glm::dvec2(
|
||||
averageRadius + _labelsMinHeight
|
||||
);
|
||||
fadeRange.x += _labelsFadeInDist;
|
||||
double a = 1.0 / (fadeRange.y - fadeRange.x);
|
||||
double b = -(fadeRange.x / (fadeRange.y - fadeRange.x));
|
||||
double funcValue = a * distanceCameraGlobeWorld + b;
|
||||
varyingOpacity *= static_cast<float>(std::min(funcValue, 1.0));
|
||||
|
||||
if (varyingOpacity < minTransparencyValueConst) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (_labelsFadeOutEnabled) {
|
||||
double averageRadius = (
|
||||
_globe->ellipsoid().radii().x + _globe->ellipsoid().radii().y +
|
||||
_globe->ellipsoid().radii().z
|
||||
) / 3.0;
|
||||
|
||||
glm::dvec2 fadeRange = glm::dvec2(
|
||||
averageRadius + _labelsMinHeight + labelFadeRangeConst
|
||||
);
|
||||
fadeRange.x += _labelsFadeOutDist;
|
||||
double a = rangeAngularCoefConst / (fadeRange.x - fadeRange.y);
|
||||
double b = -(fadeRange.y / (fadeRange.x - fadeRange.y));
|
||||
double funcValue = a * distanceCameraGlobeWorld + b;
|
||||
varyingOpacity *= static_cast<float>(std::min(funcValue, 1.0));
|
||||
|
||||
if (varyingOpacity < minTransparencyValueConst) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
renderLabels(data, mvp, static_cast<float>(distanceCameraGlobeWorld), varyingOpacity);
|
||||
}
|
||||
|
||||
void GlobeLabelsComponent::renderLabels(const RenderData& data,
|
||||
const glm::dmat4& modelViewProjectionMatrix,
|
||||
float distToCamera,
|
||||
float fadeInVariable
|
||||
) {
|
||||
constexpr double DIST_EPS = 6000.0;
|
||||
constexpr double SIN_EPS = 0.001;
|
||||
|
||||
glm::vec4 textColor = _labelsColor;
|
||||
textColor.a *= fadeInVariable;
|
||||
|
||||
glm::dmat4 invMP = glm::inverse(_globe->modelTransform());
|
||||
glm::dmat4 invCombinedView = glm::inverse(data.camera.combinedViewMatrix());
|
||||
|
||||
glm::dvec4 cameraPosWorld = invCombinedView * glm::dvec4(0.0, 0.0, 0.0, 1.0);
|
||||
glm::dvec3 cameraPosObj = glm::dvec3(invMP * cameraPosWorld);
|
||||
glm::dvec4 cameraUpVecWorld = glm::dvec4(data.camera.lookUpVectorWorldSpace(), 0.0);
|
||||
glm::dvec3 cameraLookUpObj = glm::dvec3(invMP * cameraUpVecWorld);
|
||||
|
||||
glm::dmat4 VP = glm::dmat4(data.camera.sgctInternal.projectionMatrix()) *
|
||||
data.camera.combinedViewMatrix();
|
||||
|
||||
glm::dmat4 invModelMatrix = glm::inverse(_globe->modelTransform());
|
||||
|
||||
glm::dvec3 cameraViewDirectionObj = glm::dvec3(
|
||||
invModelMatrix * glm::dvec4(data.camera.viewDirectionWorldSpace(), 0.0)
|
||||
);
|
||||
glm::dvec3 cameraUpDirectionObj = glm::dvec3(
|
||||
invModelMatrix * glm::dvec4(data.camera.lookUpVectorWorldSpace(), 0.0)
|
||||
);
|
||||
glm::dvec3 orthoRight = glm::normalize(
|
||||
glm::cross(cameraViewDirectionObj, cameraUpDirectionObj)
|
||||
);
|
||||
if (orthoRight == glm::dvec3(0.0)) {
|
||||
glm::dvec3 otherVector(
|
||||
cameraUpDirectionObj.y,
|
||||
cameraUpDirectionObj.x,
|
||||
cameraUpDirectionObj.z
|
||||
);
|
||||
orthoRight = glm::normalize(glm::cross(otherVector, cameraViewDirectionObj));
|
||||
}
|
||||
glm::dvec3 orthoUp = glm::normalize(glm::cross(orthoRight, cameraViewDirectionObj));
|
||||
|
||||
for (const LabelEntry& lEntry : _labels.labelsArray) {
|
||||
glm::vec3 position = lEntry.geoPosition;
|
||||
glm::dvec3 locationPositionWorld =
|
||||
glm::dvec3(_globe->modelTransform() * glm::dvec4(position, 1.0));
|
||||
double distanceCameraToLabelWorld =
|
||||
glm::length(locationPositionWorld - data.camera.positionVec3());
|
||||
|
||||
if (_labelsDisableCullingEnabled ||
|
||||
((distToCamera > (distanceCameraToLabelWorld + _labelsDistaneEPS)) &&
|
||||
isLabelInFrustum(VP, locationPositionWorld)))
|
||||
{
|
||||
if (_labelAlignmentOption == Circularly) {
|
||||
glm::dvec3 labelNormalObj = glm::dvec3(
|
||||
invModelMatrix * glm::dvec4(data.camera.positionVec3(), 1.0)
|
||||
) - glm::dvec3(position);
|
||||
|
||||
glm::dvec3 labelUpDirectionObj = glm::dvec3(position);
|
||||
|
||||
orthoRight = glm::normalize(
|
||||
glm::cross(labelUpDirectionObj, labelNormalObj)
|
||||
);
|
||||
if (orthoRight == glm::dvec3(0.0)) {
|
||||
glm::dvec3 otherVector(
|
||||
labelUpDirectionObj.y,
|
||||
labelUpDirectionObj.x,
|
||||
labelUpDirectionObj.z
|
||||
);
|
||||
orthoRight = glm::normalize(glm::cross(otherVector, labelNormalObj));
|
||||
}
|
||||
orthoUp = glm::normalize(glm::cross(labelNormalObj, orthoRight));
|
||||
}
|
||||
|
||||
position += _labelsMinHeight;
|
||||
|
||||
ghoul::fontrendering::FontRenderer::ProjectedLabelsInformation labelInfo;
|
||||
labelInfo.orthoRight = orthoRight;
|
||||
labelInfo.orthoUp = orthoUp;
|
||||
labelInfo.minSize = _labelsMinSize;
|
||||
labelInfo.maxSize = _labelsMaxSize;
|
||||
labelInfo.cameraPos = data.camera.positionVec3();
|
||||
labelInfo.cameraLookUp = data.camera.lookUpVectorWorldSpace();
|
||||
labelInfo.renderType = 0;
|
||||
labelInfo.mvpMatrix = modelViewProjectionMatrix;
|
||||
labelInfo.scale = powf(2.f, _labelsSize);
|
||||
labelInfo.enableDepth = true;
|
||||
labelInfo.enableFalseDepth = true;
|
||||
labelInfo.disableTransmittance = true;
|
||||
|
||||
// Testing
|
||||
glm::dmat4 modelviewTransform = glm::dmat4(data.camera.combinedViewMatrix()) *
|
||||
_globe->modelTransform();
|
||||
labelInfo.modelViewMatrix = modelviewTransform;
|
||||
labelInfo.projectionMatrix = glm::dmat4(
|
||||
data.camera.sgctInternal.projectionMatrix()
|
||||
);
|
||||
|
||||
ghoul::fontrendering::FontRenderer::defaultProjectionRenderer().render(
|
||||
*_font,
|
||||
position,
|
||||
lEntry.feature,
|
||||
textColor,
|
||||
labelInfo
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool GlobeLabelsComponent::isLabelInFrustum(const glm::dmat4& MVMatrix,
|
||||
const glm::dvec3& position) const
|
||||
{
|
||||
|
||||
// Frustum Planes
|
||||
glm::dvec3 col1(MVMatrix[0][0], MVMatrix[1][0], MVMatrix[2][0]);
|
||||
glm::dvec3 col2(MVMatrix[0][1], MVMatrix[1][1], MVMatrix[2][1]);
|
||||
glm::dvec3 col3(MVMatrix[0][2], MVMatrix[1][2], MVMatrix[2][2]);
|
||||
glm::dvec3 col4(MVMatrix[0][3], MVMatrix[1][3], MVMatrix[2][3]);
|
||||
|
||||
glm::dvec3 leftNormal = col4 + col1;
|
||||
glm::dvec3 rightNormal = col4 - col1;
|
||||
glm::dvec3 bottomNormal = col4 + col2;
|
||||
glm::dvec3 topNormal = col4 - col2;
|
||||
glm::dvec3 nearNormal = col3 + col4;
|
||||
glm::dvec3 farNormal = col4 - col3;
|
||||
|
||||
// Plane Distances
|
||||
double leftDistance = MVMatrix[3][3] + MVMatrix[3][0];
|
||||
double rightDistance = MVMatrix[3][3] - MVMatrix[3][0];
|
||||
double bottomDistance = MVMatrix[3][3] + MVMatrix[3][1];
|
||||
double topDistance = MVMatrix[3][3] - MVMatrix[3][1];
|
||||
double nearDistance = MVMatrix[3][3] + MVMatrix[3][2];
|
||||
double farDistance = MVMatrix[3][3] - MVMatrix[3][2];
|
||||
|
||||
// Normalize Planes
|
||||
double invMag = 1.0 / glm::length(leftNormal);
|
||||
leftNormal *= invMag;
|
||||
leftDistance *= invMag;
|
||||
|
||||
invMag = 1.0 / glm::length(rightNormal);
|
||||
rightNormal *= invMag;
|
||||
rightDistance *= invMag;
|
||||
|
||||
invMag = 1.0 / glm::length(bottomNormal);
|
||||
bottomNormal *= invMag;
|
||||
bottomDistance *= invMag;
|
||||
|
||||
invMag = 1.0 / glm::length(topNormal);
|
||||
topNormal *= invMag;
|
||||
topDistance *= invMag;
|
||||
|
||||
invMag = 1.0 / glm::length(nearNormal);
|
||||
nearNormal *= invMag;
|
||||
nearDistance *= invMag;
|
||||
|
||||
invMag = 1.0 / glm::length(farNormal);
|
||||
farNormal *= invMag;
|
||||
farDistance *= invMag;
|
||||
|
||||
float radius = 1.0;
|
||||
|
||||
if ((glm::dot(leftNormal, position) + leftDistance) < -radius) {
|
||||
return false;
|
||||
}
|
||||
else if ((glm::dot(rightNormal, position) + rightDistance) < -radius) {
|
||||
return false;
|
||||
}
|
||||
else if ((glm::dot(bottomNormal, position) + bottomDistance) < -radius) {
|
||||
return false;
|
||||
}
|
||||
else if ((glm::dot(topNormal, position) + topDistance) < -radius) {
|
||||
return false;
|
||||
}
|
||||
else if ((glm::dot(nearNormal, position) + nearDistance) < -radius) {
|
||||
return false;
|
||||
}
|
||||
// The far plane testing is disabled because the atm has no depth.
|
||||
/*else if ((glm::dot(farNormal, position) + farDistance) < -radius) {
|
||||
return false;
|
||||
}*/
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
121
modules/globebrowsing/src/globelabelscomponent.h
Normal file
121
modules/globebrowsing/src/globelabelscomponent.h
Normal file
@@ -0,0 +1,121 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2019 *
|
||||
* *
|
||||
* 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_GLOBEBROWSING___GLOBELABELSCOMPONENT___H__
|
||||
#define __OPENSPACE_MODULE_GLOBEBROWSING___GLOBELABELSCOMPONENT___H__
|
||||
|
||||
#include <openspace/properties/propertyowner.h>
|
||||
|
||||
#include <openspace/properties/optionproperty.h>
|
||||
#include <openspace/properties/scalar/boolproperty.h>
|
||||
#include <openspace/properties/scalar/floatproperty.h>
|
||||
#include <openspace/properties/scalar/intproperty.h>
|
||||
#include <openspace/properties/vector/vec4property.h>
|
||||
#include <ghoul/font/fontrenderer.h>
|
||||
#include <ghoul/glm.h>
|
||||
|
||||
namespace ghoul { class Dictionary;}
|
||||
namespace ghoul::opengl { class ProgramObject; }
|
||||
|
||||
namespace openspace {
|
||||
|
||||
struct RenderData;
|
||||
|
||||
namespace documentation { struct Documentation; }
|
||||
namespace globebrowsing { class RenderableGlobe; }
|
||||
|
||||
class GlobeLabelsComponent : public properties::PropertyOwner {
|
||||
public:
|
||||
enum LabelRenderingAlignmentType {
|
||||
Horizontally = 0,
|
||||
Circularly
|
||||
};
|
||||
|
||||
// Labels Structures
|
||||
struct LabelEntry {
|
||||
char feature[256];
|
||||
float diameter;
|
||||
float latitude;
|
||||
float longitude;
|
||||
glm::vec3 geoPosition;
|
||||
};
|
||||
struct Labels {
|
||||
std::string filename;
|
||||
std::vector<LabelEntry> labelsArray;
|
||||
};
|
||||
|
||||
const double labelFadeRangeConst = 1500.0;
|
||||
const double rangeAngularCoefConst = 0.8;
|
||||
const float minTransparencyValueConst = 0.009f;
|
||||
|
||||
GlobeLabelsComponent();
|
||||
~GlobeLabelsComponent() = default;
|
||||
|
||||
void initialize(const ghoul::Dictionary& dictionary,
|
||||
globebrowsing::RenderableGlobe* globe);
|
||||
|
||||
void initializeFonts();
|
||||
|
||||
static documentation::Documentation Documentation();
|
||||
|
||||
void draw(const RenderData& data);
|
||||
|
||||
private:
|
||||
bool loadLabelsData(const std::string& file);
|
||||
bool readLabelsFile(const std::string& file);
|
||||
bool loadCachedFile(const std::string& file);
|
||||
bool saveCachedFile(const std::string& file) const;
|
||||
void renderLabels(const RenderData& data, const glm::dmat4& modelViewProjectionMatrix,
|
||||
float distToCamera, float fadeInVariable);
|
||||
bool isLabelInFrustum(const glm::dmat4& MVMatrix, const glm::dvec3& position) const;
|
||||
|
||||
protected:
|
||||
properties::BoolProperty _labelsEnabled;
|
||||
properties::FloatProperty _labelsFontSize;
|
||||
properties::IntProperty _labelsMaxSize;
|
||||
properties::IntProperty _labelsMinSize;
|
||||
properties::FloatProperty _labelsSize;
|
||||
properties::FloatProperty _labelsMinHeight;
|
||||
properties::Vec4Property _labelsColor;
|
||||
properties::FloatProperty _labelsFadeInDist;
|
||||
properties::FloatProperty _labelsFadeOutDist;
|
||||
properties::BoolProperty _labelsFadeInEnabled;
|
||||
properties::BoolProperty _labelsFadeOutEnabled;
|
||||
properties::BoolProperty _labelsDisableCullingEnabled;
|
||||
properties::FloatProperty _labelsDistaneEPS;
|
||||
properties::OptionProperty _labelAlignmentOption;
|
||||
|
||||
private:
|
||||
Labels _labels;
|
||||
|
||||
// Font
|
||||
std::shared_ptr<ghoul::fontrendering::Font> _font;
|
||||
|
||||
// Globe
|
||||
openspace::globebrowsing::RenderableGlobe* _globe;
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___GLOBELABELSCOMPONENT___H__
|
||||
@@ -69,6 +69,8 @@ namespace {
|
||||
constexpr const char* KeyShadowGroup = "ShadowGroup";
|
||||
constexpr const char* KeyShadowSource = "Source";
|
||||
constexpr const char* KeyShadowCaster = "Caster";
|
||||
constexpr const char* KeyLabels = "Labels";
|
||||
|
||||
const openspace::globebrowsing::AABB3 CullingFrustum{
|
||||
glm::vec3(-1.f, -1.f, 0.f),
|
||||
glm::vec3( 1.f, 1.f, 1e35)
|
||||
@@ -541,8 +543,8 @@ RenderableGlobe::RenderableGlobe(const ghoul::Dictionary& dictionary)
|
||||
|
||||
std::vector<Ellipsoid::ShadowConfiguration> shadowConfArray;
|
||||
if (!disableShadows && (!sourceArray.empty() && !casterArray.empty())) {
|
||||
for (const auto & source : sourceArray) {
|
||||
for (const auto & caster : casterArray) {
|
||||
for (const std::pair<std::string, double>& source : sourceArray) {
|
||||
for (const std::pair<std::string, double>& caster : casterArray) {
|
||||
Ellipsoid::ShadowConfiguration sc;
|
||||
sc.source = source;
|
||||
sc.caster = caster;
|
||||
@@ -553,9 +555,17 @@ RenderableGlobe::RenderableGlobe(const ghoul::Dictionary& dictionary)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Labels Dictionary
|
||||
if (dictionary.hasKeyAndValue<ghoul::Dictionary>(KeyLabels)) {
|
||||
_labelsDictionary = dictionary.value<ghoul::Dictionary>(KeyLabels);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderableGlobe::initializeGL() {
|
||||
_globeLabelsComponent.initialize(_labelsDictionary, this);
|
||||
addPropertySubOwner(_globeLabelsComponent);
|
||||
|
||||
_layerManager.update();
|
||||
|
||||
_grid.initializeGL();
|
||||
@@ -603,11 +613,10 @@ void RenderableGlobe::render(const RenderData& data, RendererTasks& rendererTask
|
||||
if (distanceToCamera < distance) {
|
||||
try {
|
||||
renderChunks(data, rendererTask);
|
||||
_globeLabelsComponent.draw(data);
|
||||
}
|
||||
catch (const ghoul::opengl::TextureUnit::TextureUnitError&) {
|
||||
std::string layer = _lastChangedLayer ?
|
||||
_lastChangedLayer->guiName() :
|
||||
"";
|
||||
std::string layer = _lastChangedLayer ? _lastChangedLayer->guiName() : "";
|
||||
|
||||
LWARNINGC(
|
||||
guiName(),
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
|
||||
#include <modules/globebrowsing/src/ellipsoid.h>
|
||||
#include <modules/globebrowsing/src/geodeticpatch.h>
|
||||
#include <modules/globebrowsing/src/globelabelscomponent.h>
|
||||
#include <modules/globebrowsing/src/gpulayergroup.h>
|
||||
#include <modules/globebrowsing/src/layermanager.h>
|
||||
#include <modules/globebrowsing/src/skirtedgrid.h>
|
||||
@@ -247,6 +248,10 @@ private:
|
||||
bool _chunkCornersDirty = true;
|
||||
bool _nLayersIsDirty = true;
|
||||
Layer* _lastChangedLayer = nullptr;
|
||||
|
||||
// Labels
|
||||
GlobeLabelsComponent _globeLabelsComponent;
|
||||
ghoul::Dictionary _labelsDictionary;
|
||||
};
|
||||
|
||||
} // namespace openspace::globebrowsing
|
||||
|
||||
Reference in New Issue
Block a user