Merge branch 'master' of https://github.com/OpenSpace/OpenSpace into thesis/2020/software-integration

This commit is contained in:
aniisaaden
2020-10-20 09:51:10 +02:00
72 changed files with 1553 additions and 1287 deletions
@@ -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();
}
}
+1 -1
View File
@@ -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)
+51 -34
View File
@@ -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
+6 -1
View File
@@ -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__
+57 -81
View File
@@ -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) {
+22 -8
View File
@@ -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(