mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-05-20 02:58:31 -05:00
Merge branch 'master' of https://github.com/OpenSpace/OpenSpace into thesis/2020/software-integration
This commit is contained in:
@@ -404,7 +404,6 @@ void DashboardItemAngle::render(glm::vec2& penPosition) {
|
||||
|
||||
std::fill(_buffer.begin(), _buffer.end(), 0);
|
||||
if (glm::length(a) == 0.0 || glm::length(b) == 0) {
|
||||
penPosition.y -= _font->height();
|
||||
char* end = fmt::format_to(
|
||||
_buffer.data(),
|
||||
"Could not compute angle at {} between {} and {}",
|
||||
@@ -412,13 +411,13 @@ void DashboardItemAngle::render(glm::vec2& penPosition) {
|
||||
);
|
||||
std::string_view text = std::string_view(_buffer.data(), end - _buffer.data());
|
||||
RenderFont(*_font, penPosition, text);
|
||||
penPosition.y -= _font->height();
|
||||
}
|
||||
else {
|
||||
const double angle = glm::degrees(
|
||||
glm::acos(glm::dot(a, b) / (glm::length(a) * glm::length(b)))
|
||||
);
|
||||
|
||||
penPosition.y -= _font->height();
|
||||
char* end = fmt::format_to(
|
||||
_buffer.data(),
|
||||
"Angle at {} between {} and {}: {} degrees",
|
||||
@@ -426,6 +425,7 @@ void DashboardItemAngle::render(glm::vec2& penPosition) {
|
||||
);
|
||||
std::string_view text = std::string_view(_buffer.data(), end - _buffer.data());
|
||||
RenderFont(*_font, penPosition, text);
|
||||
penPosition.y -= _font->height();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -113,12 +113,12 @@ DashboardItemDate::DashboardItemDate(const ghoul::Dictionary& dictionary)
|
||||
void DashboardItemDate::render(glm::vec2& penPosition) {
|
||||
ZoneScoped
|
||||
|
||||
penPosition.y -= _font->height();
|
||||
RenderFont(
|
||||
*_font,
|
||||
penPosition,
|
||||
fmt::format("Date: {} UTC", global::timeManager.time().UTC())
|
||||
);
|
||||
penPosition.y -= _font->height();
|
||||
}
|
||||
|
||||
glm::vec2 DashboardItemDate::size() const {
|
||||
|
||||
@@ -444,7 +444,6 @@ void DashboardItemDistance::render(glm::vec2& penPosition) {
|
||||
dist = { convertedD, nameForDistanceUnit(unit, convertedD != 1.0) };
|
||||
}
|
||||
|
||||
penPosition.y -= _font->height();
|
||||
std::fill(_buffer.begin(), _buffer.end(), 0);
|
||||
char* end = fmt::format_to(
|
||||
_buffer.data(),
|
||||
@@ -454,6 +453,7 @@ void DashboardItemDistance::render(glm::vec2& penPosition) {
|
||||
|
||||
std::string_view text = std::string_view(_buffer.data(), end - _buffer.data());
|
||||
RenderFont(*_font, penPosition, text);
|
||||
penPosition.y -= _font->height();
|
||||
}
|
||||
|
||||
glm::vec2 DashboardItemDistance::size() const {
|
||||
|
||||
@@ -149,6 +149,21 @@ namespace {
|
||||
throw ghoul::MissingCaseException();
|
||||
}
|
||||
}
|
||||
|
||||
[[ nodiscard ]] int nLines(
|
||||
openspace::DashboardItemFramerate::FrametimeType frametimeType)
|
||||
{
|
||||
using FrametimeType = openspace::DashboardItemFramerate::FrametimeType;
|
||||
switch (frametimeType) {
|
||||
case FrametimeType::DtTimeAvg: return 1;
|
||||
case FrametimeType::DtTimeExtremes: return 2;
|
||||
case FrametimeType::DtStandardDeviation: return 1;
|
||||
case FrametimeType::DtCoefficientOfVariation: return 1;
|
||||
case FrametimeType::FPS: return 1;
|
||||
case FrametimeType::FPSAvg: return 1;
|
||||
default: throw ghoul::MissingCaseException();
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
@@ -309,13 +324,12 @@ void DashboardItemFramerate::render(glm::vec2& penPosition) {
|
||||
int nLines = output.empty() ? 0 :
|
||||
static_cast<int>((std::count(output.begin(), output.end(), '\n') + 1));
|
||||
|
||||
penPosition.y -= _font->height() * static_cast<float>(nLines);
|
||||
|
||||
ghoul::fontrendering::FontRenderer::defaultRenderer().render(
|
||||
*_font,
|
||||
penPosition,
|
||||
output
|
||||
);
|
||||
penPosition.y -= _font->height() * static_cast<float>(nLines);
|
||||
}
|
||||
|
||||
glm::vec2 DashboardItemFramerate::size() const {
|
||||
|
||||
@@ -209,7 +209,6 @@ void DashboardItemMission::render(glm::vec2& penPosition) {
|
||||
1.0 - remaining / phase->timeRange().duration()
|
||||
);
|
||||
const std::string progress = progressToStr(25, t);
|
||||
penPosition.y -= _font->height();
|
||||
RenderFont(
|
||||
*_font,
|
||||
penPosition,
|
||||
@@ -219,16 +218,17 @@ void DashboardItemMission::render(glm::vec2& penPosition) {
|
||||
),
|
||||
currentMissionColor
|
||||
);
|
||||
penPosition.y -= _font->height();
|
||||
}
|
||||
else {
|
||||
if (!phase->name().empty()) {
|
||||
penPosition.y -= _font->height();
|
||||
RenderFont(
|
||||
*_font,
|
||||
penPosition,
|
||||
phase->name(),
|
||||
nonCurrentMissionColor
|
||||
);
|
||||
penPosition.y -= _font->height();
|
||||
}
|
||||
}
|
||||
penPosition.x -= depth * PixelIndentation;
|
||||
|
||||
@@ -121,6 +121,8 @@ void DashboardItemParallelConnection::render(glm::vec2& penPosition) {
|
||||
const size_t nConnections = global::parallelPeer.nConnections();
|
||||
const std::string& hostName = global::parallelPeer.hostName();
|
||||
|
||||
int nLines = 1;
|
||||
|
||||
std::string connectionInfo;
|
||||
int nClients = static_cast<int>(nConnections);
|
||||
if (status == ParallelConnection::Status::Host) {
|
||||
@@ -158,11 +160,13 @@ void DashboardItemParallelConnection::render(glm::vec2& penPosition) {
|
||||
else if (nClients == 1) {
|
||||
connectionInfo += "You are the only client";
|
||||
}
|
||||
|
||||
nLines = 2;
|
||||
}
|
||||
|
||||
if (!connectionInfo.empty()) {
|
||||
penPosition.y -= _font->height();
|
||||
RenderFont(*_font, penPosition, connectionInfo);
|
||||
penPosition.y -= _font->height() * nLines;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -163,8 +163,8 @@ void DashboardItemPropertyValue::render(glm::vec2& penPosition) {
|
||||
std::string value;
|
||||
_property->getStringValue(value);
|
||||
|
||||
penPosition.y -= _font->height();
|
||||
RenderFont(*_font, penPosition, fmt::format(_displayString.value(), value));
|
||||
penPosition.y -= _font->height();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -203,7 +203,6 @@ void DashboardItemSimulationIncrement::render(glm::vec2& penPosition) {
|
||||
|
||||
std::string pauseText = global::timeManager.isPaused() ? " (Paused)" : "";
|
||||
|
||||
penPosition.y -= _font->height();
|
||||
if (targetDt != currentDt && !global::timeManager.isPaused()) {
|
||||
// We are in the middle of a transition
|
||||
RenderFont(
|
||||
@@ -227,6 +226,7 @@ void DashboardItemSimulationIncrement::render(glm::vec2& penPosition) {
|
||||
)
|
||||
);
|
||||
}
|
||||
penPosition.y -= _font->height();
|
||||
}
|
||||
|
||||
glm::vec2 DashboardItemSimulationIncrement::size() const {
|
||||
|
||||
@@ -208,7 +208,6 @@ void DashboardItemVelocity::render(glm::vec2& penPosition) {
|
||||
dist = { convertedD, nameForDistanceUnit(unit, convertedD != 1.0) };
|
||||
}
|
||||
|
||||
penPosition.y -= _font->height();
|
||||
RenderFont(
|
||||
*_font,
|
||||
penPosition,
|
||||
@@ -216,6 +215,7 @@ void DashboardItemVelocity::render(glm::vec2& penPosition) {
|
||||
"Camera velocity: {} {}/s", dist.first, dist.second
|
||||
)
|
||||
);
|
||||
penPosition.y -= _font->height();
|
||||
|
||||
_prevPosition = currentPos;
|
||||
}
|
||||
|
||||
@@ -120,24 +120,30 @@ void RenderablePlaneImageOnline::update(const UpdateData&) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::unique_ptr<ghoul::opengl::Texture> texture =
|
||||
ghoul::io::TextureReader::ref().loadTexture(
|
||||
reinterpret_cast<void*>(imageFile.buffer),
|
||||
imageFile.size,
|
||||
imageFile.format
|
||||
);
|
||||
try {
|
||||
std::unique_ptr<ghoul::opengl::Texture> texture =
|
||||
ghoul::io::TextureReader::ref().loadTexture(
|
||||
reinterpret_cast<void*>(imageFile.buffer),
|
||||
imageFile.size,
|
||||
imageFile.format
|
||||
);
|
||||
|
||||
if (texture) {
|
||||
// Images don't need to start on 4-byte boundaries, for example if the
|
||||
// image is only RGB
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
if (texture) {
|
||||
// Images don't need to start on 4-byte boundaries, for example if the
|
||||
// image is only RGB
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
|
||||
texture->uploadTexture();
|
||||
texture->setFilter(ghoul::opengl::Texture::FilterMode::LinearMipMap);
|
||||
texture->purgeFromRAM();
|
||||
texture->uploadTexture();
|
||||
texture->setFilter(ghoul::opengl::Texture::FilterMode::LinearMipMap);
|
||||
texture->purgeFromRAM();
|
||||
|
||||
_texture = std::move(texture);
|
||||
_texture = std::move(texture);
|
||||
_textureIsDirty = false;
|
||||
}
|
||||
}
|
||||
catch (const ghoul::io::TextureReader::InvalidLoadException& e) {
|
||||
_textureIsDirty = false;
|
||||
LERRORC(e.component, e.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,25 +129,31 @@ void ScreenSpaceImageOnline::update() {
|
||||
return;
|
||||
}
|
||||
|
||||
std::unique_ptr<ghoul::opengl::Texture> texture =
|
||||
ghoul::io::TextureReader::ref().loadTexture(
|
||||
reinterpret_cast<void*>(imageFile.buffer),
|
||||
imageFile.size,
|
||||
imageFile.format
|
||||
);
|
||||
try {
|
||||
std::unique_ptr<ghoul::opengl::Texture> texture =
|
||||
ghoul::io::TextureReader::ref().loadTexture(
|
||||
reinterpret_cast<void*>(imageFile.buffer),
|
||||
imageFile.size,
|
||||
imageFile.format
|
||||
);
|
||||
|
||||
if (texture) {
|
||||
// Images don't need to start on 4-byte boundaries, for example if the
|
||||
// image is only RGB
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
if (texture) {
|
||||
// Images don't need to start on 4-byte boundaries, for example if the
|
||||
// image is only RGB
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
|
||||
texture->uploadTexture();
|
||||
texture->setFilter(ghoul::opengl::Texture::FilterMode::LinearMipMap);
|
||||
texture->purgeFromRAM();
|
||||
texture->uploadTexture();
|
||||
texture->setFilter(ghoul::opengl::Texture::FilterMode::LinearMipMap);
|
||||
texture->purgeFromRAM();
|
||||
|
||||
_texture = std::move(texture);
|
||||
_objectSize = _texture->dimensions();
|
||||
_texture = std::move(texture);
|
||||
_objectSize = _texture->dimensions();
|
||||
_textureIsDirty = false;
|
||||
}
|
||||
}
|
||||
catch (const ghoul::io::TextureReader::InvalidLoadException& e) {
|
||||
_textureIsDirty = false;
|
||||
LERRORC(e.component, e.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,6 +186,12 @@ namespace {
|
||||
"astronomical objects."
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo OptionColorRangeInfo = {
|
||||
"OptionColorRange",
|
||||
"Option Color Range",
|
||||
"This value changes the range of values to be mapped with the current color map."
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo SizeOptionInfo = {
|
||||
"SizeOption",
|
||||
"Size Option Variable",
|
||||
@@ -251,6 +257,19 @@ namespace {
|
||||
"Enable pixel size control.",
|
||||
"Enable pixel size control for rectangular projections."
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo UseLinearFiltering = {
|
||||
"UseLinearFiltering",
|
||||
"Use Linear Filtering",
|
||||
"Determines whether the provided color map should be sampled nearest neighbor "
|
||||
"(=off) or linearly (=on"
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo SetRangeFromData = {
|
||||
"SetRangeFromData",
|
||||
"Set Data Range from Data",
|
||||
"Set the data range based on the available data"
|
||||
};
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
@@ -416,6 +435,12 @@ documentation::Documentation RenderableBillboardsCloud::Documentation() {
|
||||
new BoolVerifier,
|
||||
Optional::Yes,
|
||||
PixelSizeControlInfo.description
|
||||
},
|
||||
{
|
||||
UseLinearFiltering.identifier,
|
||||
new BoolVerifier,
|
||||
Optional::Yes,
|
||||
UseLinearFiltering.description
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -435,6 +460,8 @@ RenderableBillboardsCloud::RenderableBillboardsCloud(const ghoul::Dictionary& di
|
||||
, _drawLabels(DrawLabelInfo, false)
|
||||
, _pixelSizeControl(PixelSizeControlInfo, false)
|
||||
, _colorOption(ColorOptionInfo, properties::OptionProperty::DisplayType::Dropdown)
|
||||
, _optionColorRangeData(OptionColorRangeInfo, glm::vec2(0.f))
|
||||
|
||||
, _datavarSizeOption(
|
||||
SizeOptionInfo,
|
||||
properties::OptionProperty::DisplayType::Dropdown
|
||||
@@ -451,6 +478,8 @@ RenderableBillboardsCloud::RenderableBillboardsCloud(const ghoul::Dictionary& di
|
||||
, _correctionSizeEndDistance(CorrectionSizeEndDistanceInfo, 17.f, 12.f, 25.f)
|
||||
, _correctionSizeFactor(CorrectionSizeFactorInfo, 8.f, 0.f, 20.f)
|
||||
, _renderOption(RenderOptionInfo, properties::OptionProperty::DisplayType::Dropdown)
|
||||
, _setRangeFromData(SetRangeFromData)
|
||||
, _useLinearFiltering(UseLinearFiltering, false)
|
||||
{
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
@@ -473,7 +502,7 @@ RenderableBillboardsCloud::RenderableBillboardsCloud(const ghoul::Dictionary& di
|
||||
_renderOption.addOption(RenderOptionViewDirection, "Camera View Direction");
|
||||
_renderOption.addOption(RenderOptionPositionNormal, "Camera Position Normal");
|
||||
|
||||
_renderOption = RenderOptionPositionNormal;
|
||||
_renderOption = RenderOptionViewDirection;
|
||||
if (dictionary.hasKeyAndValue<std::string>(RenderOptionInfo.identifier)) {
|
||||
const std::string o = dictionary.value<std::string>(RenderOptionInfo.identifier);
|
||||
|
||||
@@ -548,6 +577,8 @@ RenderableBillboardsCloud::RenderableBillboardsCloud(const ghoul::Dictionary& di
|
||||
}
|
||||
_colorOption.onChange([&]() {
|
||||
_dataIsDirty = true;
|
||||
const glm::vec2 colorRange = _colorRangeData[_colorOption.value()];
|
||||
_optionColorRangeData = colorRange;
|
||||
_colorOptionString = _optionConversionMap[_colorOption.value()];
|
||||
});
|
||||
addProperty(_colorOption);
|
||||
@@ -561,7 +592,14 @@ RenderableBillboardsCloud::RenderableBillboardsCloud(const ghoul::Dictionary& di
|
||||
rangeDataDict.value<glm::vec2>(std::to_string(i + 1))
|
||||
);
|
||||
}
|
||||
_optionColorRangeData = _colorRangeData[_colorRangeData.size() - 1];
|
||||
}
|
||||
_optionColorRangeData.onChange([&]() {
|
||||
const glm::vec2 colorRange = _optionColorRangeData;
|
||||
_colorRangeData[_colorOption.value()] = colorRange;
|
||||
_dataIsDirty = true;
|
||||
});
|
||||
addProperty(_optionColorRangeData);
|
||||
|
||||
if (dictionary.hasKey(ExactColorMapInfo.identifier)) {
|
||||
_isColorMapExact = dictionary.value<bool>(ExactColorMapInfo.identifier);
|
||||
@@ -696,6 +734,28 @@ RenderableBillboardsCloud::RenderableBillboardsCloud(const ghoul::Dictionary& di
|
||||
_pixelSizeControl = dictionary.value<bool>(PixelSizeControlInfo.identifier);
|
||||
addProperty(_pixelSizeControl);
|
||||
}
|
||||
|
||||
_setRangeFromData.onChange([this]() {
|
||||
const int colorMapInUse =
|
||||
_hasColorMapFile ? _variableDataPositionMap[_colorOptionString] : 0;
|
||||
|
||||
float minValue = std::numeric_limits<float>::max();
|
||||
float maxValue = std::numeric_limits<float>::min();
|
||||
for (size_t i = 0; i < _fullData.size(); i += _nValuesPerAstronomicalObject) {
|
||||
float colorIdx = _fullData[i + 3 + colorMapInUse];
|
||||
maxValue = colorIdx >= maxValue ? colorIdx : maxValue;
|
||||
minValue = colorIdx < minValue ? colorIdx : minValue;
|
||||
}
|
||||
|
||||
_optionColorRangeData = glm::vec2(minValue, maxValue);
|
||||
});
|
||||
addProperty(_setRangeFromData);
|
||||
|
||||
if (dictionary.hasKey(UseLinearFiltering.identifier)) {
|
||||
_useLinearFiltering = dictionary.value<bool>(UseLinearFiltering.identifier);
|
||||
}
|
||||
_useLinearFiltering.onChange([&]() { _dataIsDirty = true; });
|
||||
addProperty(_useLinearFiltering);
|
||||
}
|
||||
|
||||
bool RenderableBillboardsCloud::isReady() const {
|
||||
@@ -1651,11 +1711,9 @@ void RenderableBillboardsCloud::createDataSlice() {
|
||||
_slicedData.push_back(position[j]);
|
||||
biggestCoord = biggestCoord < position[j] ? position[j] : biggestCoord;
|
||||
}
|
||||
|
||||
// Note: if exact colormap option is not selected, the first color and the
|
||||
// last color in the colormap file are the outliers colors.
|
||||
int variableColor = static_cast<int>(_fullData[i + 3 + colorMapInUse]);
|
||||
int colorIndex = 0;
|
||||
float variableColor = _fullData[i + 3 + colorMapInUse];
|
||||
|
||||
float cmax, cmin;
|
||||
if (_colorRangeData.empty()) {
|
||||
@@ -1669,19 +1727,51 @@ void RenderableBillboardsCloud::createDataSlice() {
|
||||
}
|
||||
|
||||
if (_isColorMapExact) {
|
||||
colorIndex = variableColor + cmin;
|
||||
int colorIndex = variableColor + cmin;
|
||||
for (int j = 0; j < 4; ++j) {
|
||||
_slicedData.push_back(_colorMapData[colorIndex][j]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
float ncmap = static_cast<float>(_colorMapData.size());
|
||||
float normalization = ((cmax != cmin) && (ncmap > 2)) ?
|
||||
(ncmap - 2) / (cmax - cmin) : 0;
|
||||
colorIndex = (variableColor - cmin) * normalization + 1;
|
||||
colorIndex = colorIndex < 0 ? 0 : colorIndex;
|
||||
colorIndex = colorIndex >= ncmap ? ncmap - 1 : colorIndex;
|
||||
}
|
||||
if (_useLinearFiltering) {
|
||||
const float value = variableColor;
|
||||
|
||||
for (int j = 0; j < 4; ++j) {
|
||||
_slicedData.push_back(_colorMapData[colorIndex][j]);
|
||||
float valueT = (value - cmin) / (cmax - cmin); // in [0, 1)
|
||||
valueT = std::clamp(valueT, 0.f, 1.f);
|
||||
|
||||
const float idx = valueT * (_colorMapData.size() - 1);
|
||||
const int floorIdx = static_cast<int>(std::floor(idx));
|
||||
const int ceilIdx = static_cast<int>(std::ceil(idx));
|
||||
|
||||
const glm::vec4 floorColor = _colorMapData[floorIdx];
|
||||
const glm::vec4 ceilColor = _colorMapData[ceilIdx];
|
||||
|
||||
if (floorColor != ceilColor) {
|
||||
const glm::vec4 c = floorColor + idx * (ceilColor - floorColor);
|
||||
_slicedData.push_back(c.r);
|
||||
_slicedData.push_back(c.g);
|
||||
_slicedData.push_back(c.b);
|
||||
_slicedData.push_back(c.a);
|
||||
}
|
||||
else {
|
||||
_slicedData.push_back(floorColor.r);
|
||||
_slicedData.push_back(floorColor.g);
|
||||
_slicedData.push_back(floorColor.b);
|
||||
_slicedData.push_back(floorColor.a);
|
||||
}
|
||||
}
|
||||
else {
|
||||
float ncmap = static_cast<float>(_colorMapData.size());
|
||||
float normalization = ((cmax != cmin) && (ncmap > 2)) ?
|
||||
(ncmap - 2) / (cmax - cmin) : 0;
|
||||
int colorIndex = (variableColor - cmin) * normalization + 1;
|
||||
colorIndex = colorIndex < 0 ? 0 : colorIndex;
|
||||
colorIndex = colorIndex >= ncmap ? ncmap - 1 : colorIndex;
|
||||
|
||||
for (int j = 0; j < 4; ++j) {
|
||||
_slicedData.push_back(_colorMapData[colorIndex][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_hasDatavarSize) {
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
|
||||
#include <openspace/properties/optionproperty.h>
|
||||
#include <openspace/properties/stringproperty.h>
|
||||
#include <openspace/properties/triggerproperty.h>
|
||||
#include <openspace/properties/scalar/boolproperty.h>
|
||||
#include <openspace/properties/scalar/floatproperty.h>
|
||||
#include <openspace/properties/vector/vec2property.h>
|
||||
@@ -123,6 +124,7 @@ private:
|
||||
properties::BoolProperty _drawLabels;
|
||||
properties::BoolProperty _pixelSizeControl;
|
||||
properties::OptionProperty _colorOption;
|
||||
properties::Vec2Property _optionColorRangeData;
|
||||
properties::OptionProperty _datavarSizeOption;
|
||||
properties::Vec2Property _fadeInDistance;
|
||||
properties::BoolProperty _disableFadeInDistance;
|
||||
@@ -130,6 +132,8 @@ private:
|
||||
properties::FloatProperty _billboardMinSize;
|
||||
properties::FloatProperty _correctionSizeEndDistance;
|
||||
properties::FloatProperty _correctionSizeFactor;
|
||||
properties::BoolProperty _useLinearFiltering;
|
||||
properties::TriggerProperty _setRangeFromData;
|
||||
|
||||
// DEBUG:
|
||||
properties::OptionProperty _renderOption;
|
||||
|
||||
@@ -299,7 +299,7 @@ documentation::Documentation RenderablePlanesCloud::Documentation() {
|
||||
|
||||
RenderablePlanesCloud::RenderablePlanesCloud(const ghoul::Dictionary& dictionary)
|
||||
: Renderable(dictionary)
|
||||
, _scaleFactor(ScaleFactorInfo, 1.f, 0.f, 10000.f)
|
||||
, _scaleFactor(ScaleFactorInfo, 1.f, 0.f, 100.f)
|
||||
, _textColor(TextColorInfo, glm::vec3(1.f), glm::vec3(0.f), glm::vec3(1.f))
|
||||
, _textOpacity(TextOpacityInfo, 1.f, 0.f, 1.f)
|
||||
, _textSize(TextSizeInfo, 8.0, 0.5, 24.0)
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#include <modules/exoplanets/exoplanetshelper.h>
|
||||
|
||||
#include <openspace/util/spicemanager.h>
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <ghoul/fmt.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
@@ -81,6 +82,17 @@ std::string_view csvStarName(std::string_view name) {
|
||||
return name;
|
||||
}
|
||||
|
||||
bool hasSufficientData(const Exoplanet& p) {
|
||||
bool invalidPos = std::isnan(p.positionX)
|
||||
|| std::isnan(p.positionY)
|
||||
|| std::isnan(p.positionZ);
|
||||
|
||||
bool hasSemiMajorAxis = !std::isnan(p.a);
|
||||
bool hasOrbitalPeriod = !std::isnan(p.per);
|
||||
|
||||
return !invalidPos && hasSemiMajorAxis && hasOrbitalPeriod;
|
||||
}
|
||||
|
||||
std::string starColor(float bv) {
|
||||
std::ifstream colorMap(absPath(BvColormapPath), std::ios::in);
|
||||
|
||||
@@ -126,49 +138,54 @@ glm::dmat4 computeOrbitPlaneRotationMatrix(float i, float bigom, float omega) {
|
||||
return orbitPlaneRotation;
|
||||
}
|
||||
|
||||
// Rotate the original coordinate system (where x is pointing to First Point of Aries)
|
||||
// so that x is pointing from star to the sun.
|
||||
// Modified from "http://www.opengl-tutorial.org/intermediate-tutorials/
|
||||
// tutorial-17-quaternions/ #how-do-i-find-the-rotation-between-2-vectors"
|
||||
glm::dmat3 exoplanetSystemRotation(glm::dvec3 start, glm::dvec3 end) {
|
||||
glm::quat rotationQuat;
|
||||
glm::dvec3 rotationAxis;
|
||||
const float cosTheta = static_cast<float>(glm::dot(start, end));
|
||||
constexpr float Epsilon = 1E-3f;
|
||||
glm::dmat3 computeSystemRotation(glm::dvec3 starPosition) {
|
||||
const glm::dvec3 sunPosition = glm::dvec3(0.0, 0.0, 0.0);
|
||||
const glm::dvec3 starToSunVec = glm::normalize(sunPosition - starPosition);
|
||||
const glm::dvec3 galacticNorth = glm::dvec3(0.0, 0.0, 1.0);
|
||||
|
||||
if (cosTheta < -1.f + Epsilon) {
|
||||
// special case when vectors in opposite directions:
|
||||
// there is no "ideal" rotation axis
|
||||
// So guess one; any will do as long as it's perpendicular to start vector
|
||||
rotationAxis = glm::cross(glm::dvec3(0.0, 0.0, 1.0), start);
|
||||
if (glm::length2(rotationAxis) < 0.01f) {
|
||||
// bad luck, they were parallel, try again!
|
||||
rotationAxis = glm::cross(glm::dvec3(1.0, 0.0, 0.0), start);
|
||||
}
|
||||
const glm::dmat3 galacticToCelestialMatrix =
|
||||
SpiceManager::ref().positionTransformMatrix("GALACTIC", "J2000", 0.0);
|
||||
|
||||
rotationAxis = glm::normalize(rotationAxis);
|
||||
rotationQuat = glm::quat(glm::radians(180.f), rotationAxis);
|
||||
return glm::dmat3(glm::toMat4(rotationQuat));
|
||||
}
|
||||
|
||||
rotationAxis = glm::cross(start, end);
|
||||
|
||||
const float s = sqrt((1.f + cosTheta) * 2.f);
|
||||
const float invs = 1.f / s;
|
||||
|
||||
rotationQuat = glm::quat(
|
||||
s * 0.5f,
|
||||
static_cast<float>(rotationAxis.x * invs),
|
||||
static_cast<float>(rotationAxis.y * invs),
|
||||
static_cast<float>(rotationAxis.z * invs)
|
||||
const glm::dvec3 celestialNorth = glm::normalize(
|
||||
galacticToCelestialMatrix * galacticNorth
|
||||
);
|
||||
|
||||
return glm::dmat3(glm::toMat4(rotationQuat));
|
||||
// Earth's north vector projected onto the skyplane, the plane perpendicular to the
|
||||
// viewing vector (starToSunVec)
|
||||
const float celestialAngle = static_cast<float>(glm::dot(
|
||||
celestialNorth,
|
||||
starToSunVec
|
||||
));
|
||||
glm::dvec3 northProjected = glm::normalize(
|
||||
celestialNorth - (celestialAngle / glm::length(starToSunVec)) * starToSunVec
|
||||
);
|
||||
|
||||
const glm::dvec3 beta = glm::normalize(glm::cross(starToSunVec, northProjected));
|
||||
|
||||
return glm::dmat3(
|
||||
northProjected.x,
|
||||
northProjected.y,
|
||||
northProjected.z,
|
||||
beta.x,
|
||||
beta.y,
|
||||
beta.z,
|
||||
starToSunVec.x,
|
||||
starToSunVec.y,
|
||||
starToSunVec.z
|
||||
);
|
||||
}
|
||||
|
||||
std::string createIdentifier(std::string name) {
|
||||
std::replace(name.begin(), name.end(), ' ', '_');
|
||||
sanitizeNameString(name);
|
||||
return name;
|
||||
}
|
||||
|
||||
void sanitizeNameString(std::string& s) {
|
||||
// We want to avoid quotes and apostrophes in names, since they cause problems
|
||||
// when a string is translated to a script call
|
||||
s.erase(remove(s.begin(), s.end(), '\"'), s.end());
|
||||
s.erase(remove(s.begin(), s.end(), '\''), s.end());
|
||||
}
|
||||
|
||||
} // namespace openspace::exoplanets
|
||||
|
||||
@@ -72,6 +72,9 @@ std::string_view speckStarName(std::string_view name);
|
||||
// Convert speck-file specific names to the corresponding name in the csv data file
|
||||
std::string_view csvStarName(std::string_view name);
|
||||
|
||||
// Check if the exoplanet p has sufficient data for visualization
|
||||
bool hasSufficientData(const Exoplanet& p);
|
||||
|
||||
// Compute star color in RGB from b-v color index
|
||||
std::string starColor(float bv);
|
||||
|
||||
@@ -79,11 +82,13 @@ glm::dmat4 computeOrbitPlaneRotationMatrix(float i, float bigom, float omega);
|
||||
|
||||
// Rotate the original coordinate system (where x is pointing to First Point of Aries)
|
||||
// so that x is pointing from star to the sun.
|
||||
glm::dmat3 exoplanetSystemRotation(glm::dvec3 start, glm::dvec3 end);
|
||||
glm::dmat3 computeSystemRotation(glm::dvec3 starPosition);
|
||||
|
||||
// Create an identifier without whitespaces
|
||||
std::string createIdentifier(std::string name);
|
||||
|
||||
void sanitizeNameString(std::string& s);
|
||||
|
||||
} // namespace openspace::exoplanets
|
||||
|
||||
#endif // __OPENSPACE_MODULE_EXOPLANETS___EXOPLANETSMODULE___H__
|
||||
|
||||
@@ -24,12 +24,10 @@
|
||||
|
||||
#include <modules/exoplanets/exoplanetshelper.h>
|
||||
#include <openspace/engine/globals.h>
|
||||
#include <openspace/engine/moduleengine.h>
|
||||
#include <openspace/query/query.h>
|
||||
#include <openspace/scene/scenegraphnode.h>
|
||||
#include <openspace/scripting/scriptengine.h>
|
||||
#include <openspace/util/distanceconstants.h>
|
||||
#include <openspace/util/spicemanager.h>
|
||||
#include <openspace/util/timeconversion.h>
|
||||
#include <openspace/util/timemanager.h>
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
@@ -37,13 +35,7 @@
|
||||
#include <ghoul/glm.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/misc/assert.h>
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
#include <glm/gtx/transform.hpp>
|
||||
#include <cfloat>
|
||||
#include <cmath>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
namespace {
|
||||
@@ -67,7 +59,11 @@ void createExoplanetSystem(std::string_view starName) {
|
||||
const std::string starNameSpeck = std::string(speckStarName(starName));
|
||||
|
||||
const std::string starIdentifier = createIdentifier(starNameSpeck);
|
||||
const std::string guiPath = ExoplanetsGuiPath + starNameSpeck;
|
||||
|
||||
std::string sanitizedStarName = starNameSpeck;
|
||||
sanitizeNameString(sanitizedStarName);
|
||||
|
||||
const std::string guiPath = ExoplanetsGuiPath + sanitizedStarName;
|
||||
|
||||
SceneGraphNode* existingStarNode = sceneGraphNode(starIdentifier);
|
||||
if (existingStarNode) {
|
||||
@@ -118,9 +114,18 @@ void createExoplanetSystem(std::string_view starName) {
|
||||
data.seekg(location);
|
||||
data.read(reinterpret_cast<char*>(&p), sizeof(Exoplanet));
|
||||
|
||||
sanitizeNameString(name);
|
||||
planetNames.push_back(name);
|
||||
planetSystem.push_back(p);
|
||||
found = true;
|
||||
|
||||
if (!hasSufficientData(p)) {
|
||||
LERROR(fmt::format(
|
||||
"Insufficient data available for visualizion of exoplanet system: '{}'",
|
||||
starName
|
||||
));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,56 +137,13 @@ void createExoplanetSystem(std::string_view starName) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool notEnoughData = std::isnan(p.positionX) || std::isnan(p.a) || std::isnan(p.per);
|
||||
|
||||
if (notEnoughData) {
|
||||
LERROR(fmt::format(
|
||||
"Insufficient data available for representing the exoplanet system: '{}'",
|
||||
starName
|
||||
));
|
||||
return;
|
||||
}
|
||||
|
||||
const glm::dvec3 starPosition = glm::dvec3(
|
||||
p.positionX * distanceconstants::Parsec,
|
||||
p.positionY * distanceconstants::Parsec,
|
||||
p.positionZ * distanceconstants::Parsec
|
||||
);
|
||||
|
||||
const glm::dvec3 sunPosition = glm::dvec3(0.0, 0.0, 0.0);
|
||||
const glm::dvec3 starToSunVec = glm::normalize(sunPosition - starPosition);
|
||||
const glm::dvec3 galacticNorth = glm::dvec3(0.0, 0.0, 1.0);
|
||||
|
||||
const glm::dmat3 galaxticToCelestialMatrix =
|
||||
SpiceManager::ref().positionTransformMatrix("GALACTIC", "J2000", 0.0);
|
||||
|
||||
const glm::dvec3 celestialNorth = glm::normalize(
|
||||
galaxticToCelestialMatrix * galacticNorth
|
||||
);
|
||||
|
||||
// Earth's north vector projected onto the skyplane, the plane perpendicular to the
|
||||
// viewing vector (starToSunVec)
|
||||
const float celestialAngle = static_cast<float>(glm::dot(
|
||||
celestialNorth,
|
||||
starToSunVec
|
||||
));
|
||||
glm::dvec3 northProjected = glm::normalize(
|
||||
celestialNorth - (celestialAngle / glm::length(starToSunVec)) * starToSunVec
|
||||
);
|
||||
|
||||
const glm::dvec3 beta = glm::normalize(glm::cross(starToSunVec, northProjected));
|
||||
|
||||
const glm::dmat3 exoplanetSystemRotation = glm::dmat3(
|
||||
northProjected.x,
|
||||
northProjected.y,
|
||||
northProjected.z,
|
||||
beta.x,
|
||||
beta.y,
|
||||
beta.z,
|
||||
starToSunVec.x,
|
||||
starToSunVec.y,
|
||||
starToSunVec.z
|
||||
);
|
||||
const glm::dmat3 exoplanetSystemRotation = computeSystemRotation(starPosition);
|
||||
|
||||
// Star renderable globe, if we have a radius and bv color index
|
||||
std::string starGlobeRenderableString;
|
||||
@@ -243,7 +205,7 @@ void createExoplanetSystem(std::string_view starName) {
|
||||
"},"
|
||||
"Tag = {'exoplanet_system'},"
|
||||
"GUI = {"
|
||||
"Name = '" + starNameSpeck + " (Star)',"
|
||||
"Name = '" + sanitizedStarName + " (Star)',"
|
||||
"Path = '" + guiPath + "'"
|
||||
"}"
|
||||
"}";
|
||||
@@ -261,15 +223,18 @@ void createExoplanetSystem(std::string_view starName) {
|
||||
if (std::isnan(planet.ecc)) {
|
||||
planet.ecc = 0.f;
|
||||
}
|
||||
if (std::isnan(planet.i)) {
|
||||
planet.i = 90.f;
|
||||
}
|
||||
if (std::isnan(planet.bigOmega)) {
|
||||
planet.bigOmega = 180.f;
|
||||
}
|
||||
if (std::isnan(planet.omega)) {
|
||||
planet.omega = 90.f;
|
||||
}
|
||||
|
||||
// KeplerTranslation requires angles in range [0, 360]
|
||||
auto validAngle = [](float angle, float defaultValue) {
|
||||
if (std::isnan(angle)) { return defaultValue; }
|
||||
if (angle < 0.f) { return angle + 360.f; }
|
||||
if (angle > 360.f) { return angle - 360.f; }
|
||||
};
|
||||
|
||||
planet.i = validAngle(planet.i, 90.f);
|
||||
planet.bigOmega = validAngle(planet.bigOmega, 180.f);
|
||||
planet.omega = validAngle(planet.omega, 90.f);
|
||||
|
||||
Time epoch;
|
||||
std::string sEpoch;
|
||||
if (!std::isnan(planet.tt)) {
|
||||
@@ -472,10 +437,22 @@ int removeExoplanetSystem(lua_State* L) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::vector<std::string> readHostStarNames(std::ifstream& lookupTableFile) {
|
||||
std::vector<std::string> hostStarsWithSufficientData() {
|
||||
std::vector<std::string> names;
|
||||
std::string line;
|
||||
|
||||
std::ifstream lookupTableFile(absPath(LookUpTablePath));
|
||||
if (!lookupTableFile.good()) {
|
||||
LERROR(fmt::format("Failed to open lookup table file '{}'", LookUpTablePath));
|
||||
return {};
|
||||
}
|
||||
|
||||
std::ifstream data(absPath(ExoplanetsDataPath), std::ios::in | std::ios::binary);
|
||||
if (!data.good()) {
|
||||
LERROR(fmt::format("Failed to open data file '{}'", ExoplanetsDataPath));
|
||||
return {};
|
||||
}
|
||||
|
||||
// Read number of lines
|
||||
int nExoplanets = 0;
|
||||
while (getline(lookupTableFile, line)) {
|
||||
@@ -485,13 +462,26 @@ std::vector<std::string> readHostStarNames(std::ifstream& lookupTableFile) {
|
||||
lookupTableFile.seekg(0);
|
||||
names.reserve(nExoplanets);
|
||||
|
||||
Exoplanet p;
|
||||
while (getline(lookupTableFile, line)) {
|
||||
std::stringstream ss(line);
|
||||
std::string name;
|
||||
getline(ss, name, ',');
|
||||
// Remove the last two characters, that specify the planet
|
||||
name = name.substr(0, name.size() - 2);
|
||||
names.push_back(name);
|
||||
|
||||
// Don't want to list systems where there is not enough data to visualize.
|
||||
// So, test if there is before adding the name to the list.
|
||||
std::string location_s;
|
||||
getline(ss, location_s);
|
||||
long location = std::stol(location_s.c_str());
|
||||
|
||||
data.seekg(location);
|
||||
data.read(reinterpret_cast<char*>(&p), sizeof(Exoplanet));
|
||||
|
||||
if (hasSufficientData(p)) {
|
||||
names.push_back(name);
|
||||
}
|
||||
}
|
||||
|
||||
// For easier read, sort by names and remove duplicates
|
||||
@@ -504,14 +494,7 @@ std::vector<std::string> readHostStarNames(std::ifstream& lookupTableFile) {
|
||||
int getListOfExoplanets(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::getListOfExoplanets");
|
||||
|
||||
std::ifstream file(absPath(LookUpTablePath));
|
||||
if (!file.good()) {
|
||||
return ghoul::lua::luaError(
|
||||
L, fmt::format("Failed to open file '{}'", LookUpTablePath
|
||||
));
|
||||
}
|
||||
|
||||
std::vector<std::string> names = readHostStarNames(file);
|
||||
std::vector<std::string> names = hostStarsWithSufficientData();
|
||||
|
||||
lua_newtable(L);
|
||||
int number = 1;
|
||||
@@ -527,14 +510,7 @@ int getListOfExoplanets(lua_State* L) {
|
||||
int listAvailableExoplanetSystems(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::listAvailableExoplanetSystems");
|
||||
|
||||
std::ifstream file(absPath(LookUpTablePath));
|
||||
if (!file.good()) {
|
||||
return ghoul::lua::luaError(
|
||||
L, fmt::format("Failed to open file '{}'", LookUpTablePath
|
||||
));
|
||||
}
|
||||
|
||||
std::vector<std::string> names = readHostStarNames(file);
|
||||
std::vector<std::string> names = hostStarsWithSufficientData();
|
||||
|
||||
std::string output;
|
||||
for (auto it = names.begin(); it != names.end(); ++it) {
|
||||
|
||||
@@ -56,12 +56,16 @@ Fragment getFragment() {
|
||||
// Moving the origin to the center
|
||||
vec2 st = (vs_st - vec2(0.5)) * 2.0;
|
||||
|
||||
float offsetLower = textureOffset.x;
|
||||
float offsetUpper = textureOffset.y;
|
||||
float offsetIntervalSize = offsetLower + offsetUpper;
|
||||
|
||||
float AUpper = semiMajorAxis;
|
||||
float BUpper = semiMinorAxis(AUpper, eccentricity);
|
||||
float CUpper = sqrt(AUpper*AUpper - BUpper*BUpper);
|
||||
float outerApoapsisDistance = AUpper * (1 + eccentricity);
|
||||
|
||||
float ALower = AUpper - AstronomicalUnit * (textureOffset.x + textureOffset.y);
|
||||
float ALower = AUpper - AstronomicalUnit * offsetIntervalSize;
|
||||
float BLower = semiMinorAxis(ALower, eccentricity);
|
||||
float CLower = sqrt(ALower*ALower - BLower*BLower);
|
||||
float innerApoapsisDistance = ALower * (1 + eccentricity);
|
||||
@@ -91,18 +95,28 @@ Fragment getFragment() {
|
||||
|
||||
// Find outer ellipse: where along the direction does the equation == 1?
|
||||
float denominator = pow(BU_n * dir.x, 2.0) + pow(AU_n * dir.y, 2.0);
|
||||
float first = -(pow(BU_n, 2.0) * dir.x * CU_n) / denominator;
|
||||
float second = pow((pow(BU_n, 2.0) * dir.x * CU_n) / denominator, 2.0);
|
||||
float first = -(BU_n * BU_n * dir.x * CU_n) / denominator;
|
||||
float second = pow((BU_n * BU_n * dir.x * CU_n) / denominator, 2.0);
|
||||
float third = (pow(BU_n * CU_n, 2.0) - pow(AU_n * BU_n, 2.0)) / denominator;
|
||||
|
||||
float scale = first + sqrt(second - third);
|
||||
|
||||
vec2 max = dir * scale;
|
||||
vec2 min = max * (innerApoapsisDistance / outerApoapsisDistance);
|
||||
vec2 outerPoint = dir * scale;
|
||||
vec2 innerPoint = outerPoint * (innerApoapsisDistance / outerApoapsisDistance);
|
||||
|
||||
float distance1 = distance(max, min);
|
||||
float distance2 = distance(max, st);
|
||||
float textureCoord = distance2 / distance1;
|
||||
float discWidth = distance(outerPoint, innerPoint);
|
||||
float distanceFromOuterEdge = distance(outerPoint, st);
|
||||
float textureCoord = distanceFromOuterEdge / discWidth;
|
||||
|
||||
// Scale texture coordinate to handle asymmetric offset intervals
|
||||
float textureMid = offsetUpper / offsetIntervalSize;
|
||||
|
||||
if(textureCoord > textureMid) {
|
||||
textureCoord = 0.5 + 0.5 * (textureCoord - textureMid) / (1.0 - textureMid);
|
||||
}
|
||||
else {
|
||||
textureCoord = 0.5 * textureCoord / textureMid;
|
||||
}
|
||||
|
||||
vec4 diffuse = texture(discTexture, textureCoord);
|
||||
diffuse.a *= opacity;
|
||||
|
||||
@@ -363,7 +363,7 @@ vec4 calculateNight(vec4 currentColor, vec2 uv, vec3 levelWeights,
|
||||
// Filter to night side
|
||||
vec4 newColor = vec4(cosineFactor * colorSample.xyz, adjustedAlpha);
|
||||
|
||||
color = blendNightLayers#{i}(currentColor, newColor, adjustedAlpha);
|
||||
color = blendNightLayers#{i}(color, newColor, adjustedAlpha);
|
||||
}
|
||||
#endfor
|
||||
|
||||
|
||||
@@ -139,10 +139,10 @@ DashboardItemGlobeLocation::DashboardItemGlobeLocation(
|
||||
auto updateFormatString = [this]() {
|
||||
using namespace fmt::literals;
|
||||
|
||||
_formatString =
|
||||
"Position: {{:03.{0}f}}{{}}, {{:03.{0}f}}{{}} Altitude: {{}} {{}}"_format(
|
||||
_significantDigits.value()
|
||||
);
|
||||
_formatString = fmt::format(
|
||||
"Position: {{:03.{0}f}}{{}}, {{:03.{0}f}}{{}} Altitude: {{:03.{0}f}} {{}}",
|
||||
_significantDigits.value()
|
||||
);
|
||||
};
|
||||
_significantDigits.onChange(updateFormatString);
|
||||
addProperty(_significantDigits);
|
||||
@@ -199,8 +199,6 @@ void DashboardItemGlobeLocation::render(glm::vec2& penPosition) {
|
||||
|
||||
std::pair<double, std::string> dist = simplifyDistance(altitude);
|
||||
|
||||
penPosition.y -= _font->height();
|
||||
|
||||
std::fill(_buffer.begin(), _buffer.end(), 0);
|
||||
char* end = fmt::format_to(
|
||||
_buffer.data(),
|
||||
@@ -212,7 +210,9 @@ void DashboardItemGlobeLocation::render(glm::vec2& penPosition) {
|
||||
std::string_view text = std::string_view(_buffer.data(), end - _buffer.data());
|
||||
|
||||
RenderFont(*_font, penPosition, text);
|
||||
penPosition.y -= _font->height();
|
||||
}
|
||||
|
||||
glm::vec2 DashboardItemGlobeLocation::size() const {
|
||||
ZoneScoped
|
||||
|
||||
|
||||
@@ -1050,6 +1050,7 @@ void RenderableGlobe::renderChunks(const RenderData& data, RendererTasks&,
|
||||
if (_globalRenderer.updatedSinceLastCall) {
|
||||
const std::array<LayerGroup*, LayerManager::NumLayerGroups>& layerGroups =
|
||||
_layerManager.layerGroups();
|
||||
|
||||
for (size_t i = 0; i < layerGroups.size(); ++i) {
|
||||
const std::string& nameBase = layergroupid::LAYER_GROUP_IDENTIFIERS[i];
|
||||
_globalRenderer.gpuLayerGroups[i].bind(
|
||||
@@ -1074,6 +1075,7 @@ void RenderableGlobe::renderChunks(const RenderData& data, RendererTasks&,
|
||||
if (_localRenderer.updatedSinceLastCall) {
|
||||
const std::array<LayerGroup*, LayerManager::NumLayerGroups>& layerGroups =
|
||||
_layerManager.layerGroups();
|
||||
|
||||
for (size_t i = 0; i < layerGroups.size(); ++i) {
|
||||
const std::string& nameBase = layergroupid::LAYER_GROUP_IDENTIFIERS[i];
|
||||
_localRenderer.gpuLayerGroups[i].bind(
|
||||
|
||||
Reference in New Issue
Block a user