mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-01-05 03:00:58 -06:00
Merge branch 'master' into feature/os-model
* Resolve conflicts
This commit is contained in:
@@ -45,12 +45,21 @@ public:
|
||||
|
||||
private slots:
|
||||
void parseScript();
|
||||
void chooseScripts();
|
||||
|
||||
/**
|
||||
* Adds scripts to the _scriptEdit from outside dialogs
|
||||
*
|
||||
* \param scripts #std::string scripts to be appended
|
||||
*/
|
||||
void appendScriptsToTextfield(std::string scripts);
|
||||
|
||||
private:
|
||||
void createWidgets();
|
||||
|
||||
openspace::Profile& _profile;
|
||||
QTextEdit* _textScripts = nullptr;
|
||||
QPushButton* _chooseScriptsButton = nullptr;
|
||||
};
|
||||
|
||||
#endif // __OPENSPACE_UI_LAUNCHER___ADDITIONALSCRIPTS___H__
|
||||
|
||||
@@ -58,13 +58,6 @@ public:
|
||||
*/
|
||||
virtual void keyPressEvent(QKeyEvent* evt) override;
|
||||
|
||||
/**
|
||||
* Adds scripts to the _scriptEdit from outside dialogs
|
||||
*
|
||||
* \param scripts #std::string scripts to be appended
|
||||
*/
|
||||
void appendScriptsToKeybind(const std::string& scripts);
|
||||
|
||||
private slots:
|
||||
void listItemSelected();
|
||||
void listItemAdded();
|
||||
@@ -76,6 +69,13 @@ private slots:
|
||||
void chooseScripts();
|
||||
void keySelected(int index);
|
||||
|
||||
/**
|
||||
* Adds scripts to the _scriptEdit from outside dialogs
|
||||
*
|
||||
* \param scripts #std::string scripts to be appended
|
||||
*/
|
||||
void appendScriptsToKeybind(std::string scripts);
|
||||
|
||||
private:
|
||||
void createWidgets();
|
||||
void transitionFromEditMode();
|
||||
|
||||
@@ -35,10 +35,12 @@ public:
|
||||
/**
|
||||
* Constructor for ScriptlogDialog class
|
||||
*
|
||||
* \param bindingDialog keybindingDialog that openend this window.
|
||||
* \param parent Pointer to parent Qt widget
|
||||
*/
|
||||
ScriptlogDialog(KeybindingsDialog* bindingDialog, QWidget* parent);
|
||||
ScriptlogDialog(QWidget* parent);
|
||||
|
||||
signals:
|
||||
void scriptsSelected(std::string script);
|
||||
|
||||
private slots:
|
||||
void saveChosenScripts();
|
||||
@@ -46,7 +48,6 @@ private slots:
|
||||
private:
|
||||
void createWidgets();
|
||||
|
||||
KeybindingsDialog* _bindingDialog = nullptr;
|
||||
QListWidget* _scriptlogList = nullptr;
|
||||
};
|
||||
|
||||
|
||||
@@ -25,10 +25,12 @@
|
||||
#include "profile/additionalscriptsdialog.h"
|
||||
|
||||
#include "profile/line.h"
|
||||
#include "profile/scriptlogdialog.h"
|
||||
#include <openspace/scene/profile.h>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
#include <QTextEdit>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
@@ -61,6 +63,13 @@ void AdditionalScriptsDialog::createWidgets() {
|
||||
_textScripts->setAcceptRichText(false);
|
||||
layout->addWidget(_textScripts, 1);
|
||||
|
||||
_chooseScriptsButton = new QPushButton("Choose Scripts");
|
||||
connect(
|
||||
_chooseScriptsButton, &QPushButton::clicked,
|
||||
this, &AdditionalScriptsDialog::chooseScripts
|
||||
);
|
||||
layout->addWidget(_chooseScriptsButton);
|
||||
|
||||
layout->addWidget(new Line);
|
||||
|
||||
{
|
||||
@@ -89,3 +98,13 @@ void AdditionalScriptsDialog::parseScript() {
|
||||
_profile.setAdditionalScripts(additionalScripts);
|
||||
accept();
|
||||
}
|
||||
|
||||
void AdditionalScriptsDialog::chooseScripts() {
|
||||
ScriptlogDialog d(this);
|
||||
connect(&d, &ScriptlogDialog::scriptsSelected, this, &AdditionalScriptsDialog::appendScriptsToTextfield);
|
||||
d.exec();
|
||||
}
|
||||
|
||||
void AdditionalScriptsDialog::appendScriptsToTextfield(std::string scripts) {
|
||||
_textScripts->append(QString::fromStdString(std::move(scripts)));
|
||||
}
|
||||
|
||||
@@ -108,8 +108,8 @@ KeybindingsDialog::KeybindingsDialog(Profile& profile, QWidget *parent)
|
||||
transitionFromEditMode();
|
||||
}
|
||||
|
||||
void KeybindingsDialog::appendScriptsToKeybind(const std::string& scripts) {
|
||||
_scriptEdit->append(QString::fromStdString(scripts));
|
||||
void KeybindingsDialog::appendScriptsToKeybind(std::string scripts) {
|
||||
_scriptEdit->append(QString::fromStdString(std::move(scripts)));
|
||||
}
|
||||
|
||||
void KeybindingsDialog::createWidgets() {
|
||||
@@ -525,7 +525,9 @@ void KeybindingsDialog::parseSelections() {
|
||||
|
||||
void KeybindingsDialog::chooseScripts() {
|
||||
_errorMsg->clear();
|
||||
ScriptlogDialog(this, this).exec();
|
||||
ScriptlogDialog d(this);
|
||||
connect(&d, &ScriptlogDialog::scriptsSelected, this, &KeybindingsDialog::appendScriptsToKeybind);
|
||||
d.exec();
|
||||
}
|
||||
|
||||
void KeybindingsDialog::keyPressEvent(QKeyEvent* evt) {
|
||||
|
||||
@@ -33,10 +33,8 @@
|
||||
#include <QTextStream>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
ScriptlogDialog::ScriptlogDialog(KeybindingsDialog* bindingDialog,
|
||||
QWidget* parent)
|
||||
ScriptlogDialog::ScriptlogDialog(QWidget* parent)
|
||||
: QDialog(parent)
|
||||
, _bindingDialog(bindingDialog)
|
||||
{
|
||||
setWindowTitle("Scriptlog");
|
||||
createWidgets();
|
||||
@@ -93,7 +91,7 @@ void ScriptlogDialog::saveChosenScripts() {
|
||||
chosenScripts += "\n";
|
||||
}
|
||||
}
|
||||
_bindingDialog->appendScriptsToKeybind(chosenScripts);
|
||||
emit scriptsSelected(chosenScripts);
|
||||
|
||||
accept();
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ local initializeAndAddNodes = function()
|
||||
local iss = {
|
||||
Identifier = "ISS",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
BoundingSphere = 30,
|
||||
InteractionSphere = 30,
|
||||
Transform = {
|
||||
Translation = {
|
||||
Type = "TLETranslation",
|
||||
|
||||
@@ -19,7 +19,7 @@ asset.onInitialize(function ()
|
||||
local Aqua = {
|
||||
Identifier = "Aqua",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
BoundingSphere = 30,
|
||||
InteractionSphere = 30,
|
||||
Transform = {
|
||||
Translation = {
|
||||
Type = "TLETranslation",
|
||||
|
||||
@@ -19,7 +19,7 @@ asset.onInitialize(function ()
|
||||
local SNPP = {
|
||||
Identifier = "SNPP",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
BoundingSphere = 30,
|
||||
InteractionSphere = 30,
|
||||
Transform = {
|
||||
Translation = {
|
||||
Type = "TLETranslation",
|
||||
|
||||
@@ -19,7 +19,7 @@ asset.onInitialize(function ()
|
||||
local Terra = {
|
||||
Identifier = "Terra",
|
||||
Parent = transforms.EarthInertial.Identifier,
|
||||
BoundingSphere = 30,
|
||||
InteractionSphere = 30,
|
||||
Transform = {
|
||||
Translation = {
|
||||
Type = "TLETranslation",
|
||||
|
||||
@@ -3,7 +3,7 @@ asset.require('./static_server')
|
||||
local guiCustomization = asset.require('customization/gui')
|
||||
|
||||
-- Select which commit hashes to use for the frontend and backend
|
||||
local frontendHash = "02d6b86e40ea4db4bd8755bf7ade22fd9d839785"
|
||||
local frontendHash = "391f8d3ed74e598a0e8a1b16016324d8f747e18d"
|
||||
local dataProvider = "data.openspaceproject.com/files/webgui"
|
||||
|
||||
local frontend = asset.syncedResource({
|
||||
|
||||
Submodule ext/ghoul updated: 9e815e8073...34864556a4
@@ -381,22 +381,21 @@ public:
|
||||
|
||||
/**
|
||||
* Default view options that can be used in the Property::setViewOption method. The
|
||||
* values are: Property::ViewOptions::Color = \c color,
|
||||
* Property::ViewOptions::LightPosition = \c lightPosition
|
||||
* values are: Property::ViewOptions::Color = \c Color,
|
||||
* Property::ViewOptions::Logarithmic = \c Logarithmic
|
||||
*/
|
||||
struct ViewOptions {
|
||||
static const char* Color;
|
||||
static const char* LightPosition;
|
||||
static const char* Logarithmic;
|
||||
};
|
||||
|
||||
/**
|
||||
* This method allows the developer to give hints to the GUI about different
|
||||
* representations for the GUI. The same Property (for example Vec4Property) can be
|
||||
* used in different ways, each requiring a different input method. These values are
|
||||
* stored in the metaData object using the <code>views.</code> prefix in front of the
|
||||
* <code>option</code> parameter. See Property::ViewOptions for a default list of
|
||||
* possible options. As these are only hints, the GUI is free to ignore any suggestion
|
||||
* by the developer.
|
||||
* stored in the metaData object under <code>ViewOptions</code>.
|
||||
* See Property::ViewOptions for a default list of possible options. As these are
|
||||
* only hints, the GUI is free to ignore any suggestion by the developer.
|
||||
* \param option The view option that should be modified
|
||||
* \param value Determines if the view option should be active (<code>true</code>) or
|
||||
* deactivated (<code>false</code>)
|
||||
|
||||
@@ -61,12 +61,12 @@ void renderBox(const glm::vec2& position, const glm::vec2& size, const glm::vec4
|
||||
struct Shaders {
|
||||
struct {
|
||||
std::unique_ptr<ghoul::opengl::ProgramObject> program;
|
||||
UniformCache(tex, hasTexture, shouldFlipTexture, ortho, color) cache;
|
||||
UniformCache(tex, hasTexture, shouldFlipTexture, proj, color) cache;
|
||||
} xyuvrgba;
|
||||
|
||||
struct {
|
||||
std::unique_ptr<ghoul::opengl::ProgramObject> program;
|
||||
UniformCache(tex, hasTexture, shouldFlipTexture, ortho, color) cache;
|
||||
UniformCache(tex, hasTexture, shouldFlipTexture, proj, color) cache;
|
||||
} screenfilling;
|
||||
};
|
||||
|
||||
@@ -76,6 +76,14 @@ struct VertexObjects {
|
||||
GLuint vbo;
|
||||
} square;
|
||||
|
||||
struct {
|
||||
GLuint vao;
|
||||
GLuint vbo;
|
||||
GLuint ibo;
|
||||
|
||||
int nElements = 64;
|
||||
} sphere;
|
||||
|
||||
struct {
|
||||
GLuint vao;
|
||||
} empty;
|
||||
@@ -108,6 +116,9 @@ std::vector<VertexXYZ> convert(std::vector<Vertex> v);
|
||||
std::vector<Vertex> createRing(int nSegments, float radius,
|
||||
glm::vec4 colors = glm::vec4(1.f));
|
||||
|
||||
std::pair<std::vector<Vertex>, std::vector<GLushort>>
|
||||
createSphere(int nSegments, glm::vec3 radii, glm::vec4 colors = glm::vec4(1.f));
|
||||
|
||||
} // namespace openspace::rendering::helper
|
||||
|
||||
#endif // __OPENSPACE_CORE___HELPER___H__
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <openspace/properties/scalar/doubleproperty.h>
|
||||
#include <openspace/properties/scalar/floatproperty.h>
|
||||
#include <openspace/properties/stringproperty.h>
|
||||
#include <openspace/scene/scenegraphnode.h>
|
||||
#include <ghoul/misc/managedmemoryuniqueptr.h>
|
||||
|
||||
namespace ghoul { class Dictionary; }
|
||||
@@ -75,11 +76,17 @@ public:
|
||||
bool isEnabled() const;
|
||||
bool shouldUpdateIfDisabled() const;
|
||||
|
||||
void setBoundingSphere(double boundingSphere);
|
||||
double boundingSphere() const;
|
||||
double interactionSphere() const;
|
||||
|
||||
virtual void render(const RenderData& data, RendererTasks& rendererTask);
|
||||
virtual void update(const UpdateData& data);
|
||||
|
||||
// The 'surface' in this case is the interaction sphere of this renderable. In some
|
||||
// cases (i.e., planets) this corresponds directly to the physical surface, but in
|
||||
// many cases, models, volumetric data, this will not. Regardless of what the physical
|
||||
// representation is, the 'surface' is always the sphere around which interaction is
|
||||
// handled
|
||||
virtual SurfacePositionHandle calculateSurfacePositionHandle(
|
||||
const glm::dvec3& targetModelSpace) const;
|
||||
|
||||
@@ -98,15 +105,25 @@ public:
|
||||
protected:
|
||||
properties::BoolProperty _enabled;
|
||||
properties::FloatProperty _opacity;
|
||||
properties::DoubleProperty _boundingSphere;
|
||||
properties::StringProperty _renderableType;
|
||||
|
||||
bool _shouldUpdateIfDisabled = false;
|
||||
void setBoundingSphere(double boundingSphere);
|
||||
|
||||
void setRenderBinFromOpacity();
|
||||
void registerUpdateRenderBinFromOpacity();
|
||||
|
||||
double _boundingSphere = 0.0;
|
||||
double _interactionSphere = 0.0;
|
||||
SceneGraphNode* _parent = nullptr;
|
||||
bool _shouldUpdateIfDisabled = false;
|
||||
|
||||
private:
|
||||
// We only want the SceneGraphNode to be able manipulate the parent, so we don't want
|
||||
// to provide a set method for this. Otherwise, anyone might mess around with our
|
||||
// parentage and that's no bueno
|
||||
friend ghoul::mm_unique_ptr<SceneGraphNode> SceneGraphNode::createFromDictionary(
|
||||
const ghoul::Dictionary&);
|
||||
|
||||
RenderBin _renderBin = RenderBin::Opaque;
|
||||
};
|
||||
|
||||
|
||||
@@ -36,14 +36,16 @@
|
||||
#include <ghoul/misc/boolean.h>
|
||||
#include <ghoul/misc/managedmemoryuniqueptr.h>
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
#include <chrono>
|
||||
|
||||
//#define Debugging_Core_SceneGraphNode_Indices
|
||||
|
||||
namespace ghoul { class Dictionary; }
|
||||
namespace ghoul::opengl { class ProgramObject; }
|
||||
|
||||
namespace openspace {
|
||||
|
||||
@@ -127,6 +129,7 @@ public:
|
||||
std::vector<SceneGraphNode*> children() const;
|
||||
|
||||
double boundingSphere() const;
|
||||
double interactionSphere() const;
|
||||
|
||||
SceneGraphNode* childNode(const std::string& identifier);
|
||||
|
||||
@@ -143,6 +146,7 @@ private:
|
||||
glm::dmat3 calculateWorldRotation() const;
|
||||
glm::dvec3 calculateWorldScale() const;
|
||||
void computeScreenSpaceData(RenderData& newData);
|
||||
void renderDebugSphere(const Camera& camera, double size, glm::vec4 color);
|
||||
|
||||
std::atomic<State> _state = State::Loaded;
|
||||
std::vector<ghoul::mm_unique_ptr<SceneGraphNode>> _children;
|
||||
@@ -178,6 +182,7 @@ private:
|
||||
glm::dmat4 _modelTransformCached = glm::dmat4(1.0);
|
||||
|
||||
properties::DoubleProperty _boundingSphere;
|
||||
properties::DoubleProperty _interactionSphere;
|
||||
properties::BoolProperty _computeScreenSpaceValues;
|
||||
properties::IVec2Property _screenSpacePosition;
|
||||
properties::BoolProperty _screenVisibility;
|
||||
@@ -189,6 +194,12 @@ private:
|
||||
// are calculated when _computeScreenSpaceValues is true)
|
||||
std::chrono::high_resolution_clock::time_point _lastScreenSpaceUpdateTime;
|
||||
|
||||
properties::BoolProperty _showDebugSphere;
|
||||
static ghoul::opengl::ProgramObject* _debugSphereProgram;
|
||||
|
||||
std::optional<double> _overrideBoundingSphere;
|
||||
std::optional<double> _overrideInteractionSphere;
|
||||
|
||||
#ifdef Debugging_Core_SceneGraphNode_Indices
|
||||
int index = 0;
|
||||
static int nextIndex;
|
||||
|
||||
@@ -50,7 +50,7 @@ struct UpdateData {
|
||||
struct RenderData {
|
||||
const Camera& camera;
|
||||
const Time time;
|
||||
int renderBinMask = -1;
|
||||
int8_t renderBinMask = -1;
|
||||
TransformData modelTransform;
|
||||
};
|
||||
|
||||
|
||||
@@ -381,6 +381,8 @@ RenderableAtmosphere::RenderableAtmosphere(const ghoul::Dictionary& dictionary)
|
||||
_hardShadowsEnabled.onChange(updateWithoutCalculation);
|
||||
addProperty(_hardShadowsEnabled);
|
||||
}
|
||||
|
||||
setBoundingSphere(_planetRadius * 1000.0);
|
||||
}
|
||||
|
||||
void RenderableAtmosphere::deinitializeGL() {
|
||||
|
||||
@@ -92,7 +92,7 @@ RenderableGrid::RenderableGrid(const ghoul::Dictionary& dictionary)
|
||||
, _color(ColorInfo, glm::vec3(0.5f), glm::vec3(0.f), glm::vec3(1.f))
|
||||
, _segments(SegmentsInfo, glm::uvec2(10), glm::uvec2(1), glm::uvec2(200))
|
||||
, _lineWidth(LineWidthInfo, 0.5f, 1.f, 20.f)
|
||||
, _size(SizeInfo, glm::vec2(1e20f), glm::vec2(1.f), glm::vec2(1e35f))
|
||||
, _size(SizeInfo, glm::vec2(1e10f), glm::vec2(1.f), glm::vec2(1e20f))
|
||||
{
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
@@ -110,6 +110,7 @@ RenderableGrid::RenderableGrid(const ghoul::Dictionary& dictionary)
|
||||
_lineWidth = p.lineWidth.value_or(_lineWidth);
|
||||
addProperty(_lineWidth);
|
||||
|
||||
_size.setViewOption(properties::Property::ViewOptions::Logarithmic);
|
||||
_size = p.size.value_or(_size);
|
||||
_size.onChange([&]() { _gridIsDirty = true; });
|
||||
addProperty(_size);
|
||||
|
||||
@@ -99,6 +99,7 @@ RenderableDisc::RenderableDisc(const ghoul::Dictionary& dictionary)
|
||||
_texturePath.onChange([&]() { _texture->loadFromFile(_texturePath); });
|
||||
addProperty(_texturePath);
|
||||
|
||||
_size.setViewOption(properties::Property::ViewOptions::Logarithmic);
|
||||
_size = p.size.value_or(_size);
|
||||
setBoundingSphere(_size);
|
||||
_size.onChange([&]() { _planeIsDirty = true; });
|
||||
|
||||
@@ -690,7 +690,7 @@ void RenderableModel::update(const UpdateData& data) {
|
||||
switch (_animationMode) {
|
||||
case AnimationMode::LoopFromStart:
|
||||
// Start looping from the start time
|
||||
// s////
|
||||
// s//// ...
|
||||
relativeTime = std::fmod(now - startTime, duration);
|
||||
break;
|
||||
case AnimationMode::LoopInfinitely:
|
||||
@@ -699,7 +699,7 @@ void RenderableModel::update(const UpdateData& data) {
|
||||
// true modulo function, it just calculates the remainder of the division
|
||||
// which can be negative. To make it true modulo it is bumped up to
|
||||
// positive values when it is negative
|
||||
// //s//
|
||||
// //s// ...
|
||||
relativeTime = std::fmod(now - startTime, duration);
|
||||
if (relativeTime < 0.0) {
|
||||
relativeTime += duration;
|
||||
@@ -711,14 +711,14 @@ void RenderableModel::update(const UpdateData& data) {
|
||||
// goes back to its initial position before starting again. Avoids a
|
||||
// visible jump from the last position to the first position when loop
|
||||
// starts again
|
||||
// s/\/\/\/\
|
||||
// s/\/\/\/\ ...
|
||||
relativeTime =
|
||||
duration - abs(fmod(now - startTime, 2 * duration) - duration);
|
||||
break;
|
||||
case AnimationMode::BounceInfinitely: {
|
||||
// Bounce both before and after the start time where the model is
|
||||
// in the initial position at the start time
|
||||
// /\/\s/\/\
|
||||
// /\/\s/\/\ ...
|
||||
double modulo = fmod(now - startTime, 2 * duration);
|
||||
if (modulo < 0.0) {
|
||||
modulo += 2 * duration;
|
||||
|
||||
@@ -127,6 +127,7 @@ RenderableNodeLine::RenderableNodeLine(const ghoul::Dictionary& dictionary)
|
||||
addProperty(_end);
|
||||
|
||||
_lineColor = p.color.value_or(_lineColor);
|
||||
_lineColor.setViewOption(properties::Property::ViewOptions::Color);
|
||||
addProperty(_lineColor);
|
||||
|
||||
_lineWidth = p.lineWidth.value_or(_lineWidth);
|
||||
|
||||
@@ -153,9 +153,11 @@ RenderablePlane::RenderablePlane(const ghoul::Dictionary& dictionary)
|
||||
}
|
||||
|
||||
_multiplyColor = p.multiplyColor.value_or(_multiplyColor);
|
||||
_multiplyColor.setViewOption(properties::Property::ViewOptions::Color);
|
||||
|
||||
addProperty(_billboard);
|
||||
|
||||
_size.setViewOption(properties::Property::ViewOptions::Logarithmic);
|
||||
addProperty(_size);
|
||||
_size.onChange([this](){ _planeIsDirty = true; });
|
||||
|
||||
|
||||
@@ -215,8 +215,12 @@ RenderableSphere::RenderableSphere(const ghoul::Dictionary& dictionary)
|
||||
}
|
||||
addProperty(_orientation);
|
||||
|
||||
_size.setViewOption(properties::Property::ViewOptions::Logarithmic);
|
||||
_size.onChange([this]() {
|
||||
setBoundingSphere(_size);
|
||||
_sphereIsDirty = true;
|
||||
});
|
||||
addProperty(_size);
|
||||
_size.onChange([this]() { _sphereIsDirty = true; });
|
||||
|
||||
addProperty(_segments);
|
||||
_segments.onChange([this]() { _sphereIsDirty = true; });
|
||||
@@ -257,6 +261,7 @@ RenderableSphere::RenderableSphere(const ghoul::Dictionary& dictionary)
|
||||
setRenderBin(Renderable::RenderBin::Background);
|
||||
}
|
||||
|
||||
setBoundingSphere(_size);
|
||||
setRenderBinFromOpacity();
|
||||
}
|
||||
|
||||
|
||||
@@ -204,6 +204,7 @@ RenderableTrail::Appearance::Appearance()
|
||||
{ RenderingModeLinesPoints, "Lines+Points" }
|
||||
});
|
||||
|
||||
lineColor.setViewOption(properties::Property::ViewOptions::Color);
|
||||
addProperty(lineColor);
|
||||
addProperty(useLineFade);
|
||||
addProperty(lineFade);
|
||||
|
||||
@@ -58,6 +58,7 @@ StaticTranslation::StaticTranslation()
|
||||
glm::dvec3(std::numeric_limits<double>::max())
|
||||
)
|
||||
{
|
||||
_position.setViewOption(properties::Property::ViewOptions::Logarithmic);
|
||||
addProperty(_position);
|
||||
|
||||
_position.onChange([this]() {
|
||||
|
||||
@@ -116,12 +116,13 @@ RenderableDebugPlane::RenderableDebugPlane(const ghoul::Dictionary& dictionary)
|
||||
|
||||
_texture = p.texture.value_or(_texture);
|
||||
addProperty(_texture);
|
||||
|
||||
|
||||
_size.setViewOption(properties::Property::ViewOptions::Logarithmic);
|
||||
_size.onChange([this](){ _planeIsDirty = true; });
|
||||
_size = p.size.value_or(_size);
|
||||
setBoundingSphere(_size);
|
||||
addProperty(_size);
|
||||
|
||||
|
||||
_billboard = p.billboard.value_or(_billboard);
|
||||
addProperty(_billboard);
|
||||
|
||||
|
||||
@@ -767,31 +767,6 @@ void RenderableBillboardsCloud::renderLabels(const RenderData& data,
|
||||
const glm::dvec3& orthoUp,
|
||||
float fadeInVariable)
|
||||
{
|
||||
float scale = 0.f;
|
||||
switch (_unit) {
|
||||
case Meter:
|
||||
scale = 1.f;
|
||||
break;
|
||||
case Kilometer:
|
||||
scale = 1e3f;
|
||||
break;
|
||||
case Parsec:
|
||||
scale = static_cast<float>(PARSEC);
|
||||
break;
|
||||
case Kiloparsec:
|
||||
scale = static_cast<float>(1e3 * PARSEC);
|
||||
break;
|
||||
case Megaparsec:
|
||||
scale = static_cast<float>(1e6 * PARSEC);
|
||||
break;
|
||||
case Gigaparsec:
|
||||
scale = static_cast<float>(1e9 * PARSEC);
|
||||
break;
|
||||
case GigalightYears:
|
||||
scale = static_cast<float>(306391534.73091 * PARSEC);
|
||||
break;
|
||||
}
|
||||
|
||||
glm::vec4 textColor = glm::vec4(
|
||||
glm::vec3(_textColor),
|
||||
_textOpacity * fadeInVariable
|
||||
@@ -813,7 +788,7 @@ void RenderableBillboardsCloud::renderLabels(const RenderData& data,
|
||||
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);
|
||||
scaledPos *= scale;
|
||||
scaledPos *= unitToMeter(_unit);
|
||||
ghoul::fontrendering::FontRenderer::defaultProjectionRenderer().render(
|
||||
*_font,
|
||||
scaledPos,
|
||||
@@ -825,36 +800,11 @@ void RenderableBillboardsCloud::renderLabels(const RenderData& data,
|
||||
}
|
||||
|
||||
void RenderableBillboardsCloud::render(const RenderData& data, RendererTasks&) {
|
||||
float scale = 0.f;
|
||||
switch (_unit) {
|
||||
case Meter:
|
||||
scale = 1.f;
|
||||
break;
|
||||
case Kilometer:
|
||||
scale = 1e3f;
|
||||
break;
|
||||
case Parsec:
|
||||
scale = static_cast<float>(PARSEC);
|
||||
break;
|
||||
case Kiloparsec:
|
||||
scale = static_cast<float>(1e3 * PARSEC);
|
||||
break;
|
||||
case Megaparsec:
|
||||
scale = static_cast<float>(1e6 * PARSEC);
|
||||
break;
|
||||
case Gigaparsec:
|
||||
scale = static_cast<float>(1e9 * PARSEC);
|
||||
break;
|
||||
case GigalightYears:
|
||||
scale = static_cast<float>(306391534.73091 * PARSEC);
|
||||
break;
|
||||
}
|
||||
|
||||
float fadeInVariable = 1.f;
|
||||
if (!_disableFadeInDistance) {
|
||||
float distCamera = static_cast<float>(glm::length(data.camera.positionVec3()));
|
||||
const glm::vec2 fadeRange = _fadeInDistance;
|
||||
const float a = 1.f / ((fadeRange.y - fadeRange.x) * scale);
|
||||
const float a = 1.f / ((fadeRange.y - fadeRange.x) * unitToMeter(_unit));
|
||||
const float b = -(fadeRange.x / (fadeRange.y - fadeRange.x));
|
||||
const float funcValue = a * distCamera + b;
|
||||
fadeInVariable *= funcValue > 1.f ? 1.f : funcValue;
|
||||
@@ -1488,6 +1438,19 @@ bool RenderableBillboardsCloud::saveCachedFile(const std::string& file) const {
|
||||
return fileStream.good();
|
||||
}
|
||||
|
||||
double RenderableBillboardsCloud::unitToMeter(Unit unit) const {
|
||||
switch (_unit) {
|
||||
case Meter: return 1.0;
|
||||
case Kilometer: return 1e3;
|
||||
case Parsec: return PARSEC;
|
||||
case Kiloparsec: return 1000 * PARSEC;
|
||||
case Megaparsec: return 1e6 * PARSEC;
|
||||
case Gigaparsec: return 1e9 * PARSEC;
|
||||
case GigalightYears: return 306391534.73091 * PARSEC;
|
||||
default: throw ghoul::MissingCaseException();
|
||||
}
|
||||
}
|
||||
|
||||
void RenderableBillboardsCloud::createDataSlice() {
|
||||
ZoneScoped
|
||||
|
||||
@@ -1516,7 +1479,7 @@ void RenderableBillboardsCloud::createDataSlice() {
|
||||
_slicedData.push_back(_fullData[i + 3 + datavarInUse]);
|
||||
};
|
||||
|
||||
auto addPosition = [&](const glm::vec4 &pos) {
|
||||
auto addPosition = [&](const glm::vec4& pos) {
|
||||
for (int j = 0; j < 4; ++j) {
|
||||
_slicedData.push_back(pos[j]);
|
||||
}
|
||||
@@ -1531,17 +1494,24 @@ void RenderableBillboardsCloud::createDataSlice() {
|
||||
minColorIdx = colorIdx < minColorIdx ? colorIdx : minColorIdx;
|
||||
}
|
||||
|
||||
double maxRadius = 0.0;
|
||||
|
||||
float biggestCoord = -1.f;
|
||||
for (size_t i = 0; i < _fullData.size(); i += _nValuesPerAstronomicalObject) {
|
||||
glm::dvec4 transformedPos = _transformationMatrix * glm::dvec4(
|
||||
glm::vec3 transformedPos = glm::vec3(_transformationMatrix * glm::vec4(
|
||||
_fullData[i + 0],
|
||||
_fullData[i + 1],
|
||||
_fullData[i + 2],
|
||||
1.0
|
||||
);
|
||||
// W-normalization
|
||||
transformedPos /= transformedPos.w;
|
||||
glm::vec4 position(glm::vec3(transformedPos), static_cast<float>(_unit));
|
||||
));
|
||||
glm::vec4 position(transformedPos, static_cast<float>(_unit));
|
||||
|
||||
const double unitMeter = unitToMeter(_unit);
|
||||
glm::dvec3 p = glm::dvec3(position) * unitMeter;
|
||||
const double r = glm::length(p);
|
||||
if (r > maxRadius) {
|
||||
maxRadius = r;
|
||||
}
|
||||
|
||||
if (_hasColorMapFile) {
|
||||
for (int j = 0; j < 4; ++j) {
|
||||
@@ -1623,6 +1593,7 @@ void RenderableBillboardsCloud::createDataSlice() {
|
||||
addPosition(position);
|
||||
}
|
||||
}
|
||||
setBoundingSphere(maxRadius);
|
||||
_fadeInDistance.setMaxValue(glm::vec2(10.f * biggestCoord));
|
||||
}
|
||||
|
||||
|
||||
@@ -76,6 +76,7 @@ private:
|
||||
Gigaparsec = 5,
|
||||
GigalightYears = 6
|
||||
};
|
||||
double unitToMeter(Unit unit) const;
|
||||
|
||||
void createDataSlice();
|
||||
void createPolygonTexture();
|
||||
|
||||
@@ -572,35 +572,12 @@ void RenderablePlanesCloud::renderLabels(const RenderData& data,
|
||||
}
|
||||
|
||||
void RenderablePlanesCloud::render(const RenderData& data, RendererTasks&) {
|
||||
float scale = 0.f;
|
||||
switch (_unit) {
|
||||
case Meter:
|
||||
scale = 1.f;
|
||||
break;
|
||||
case Kilometer:
|
||||
scale = 1e3f;
|
||||
break;
|
||||
case Parsec:
|
||||
scale = static_cast<float>(PARSEC);
|
||||
break;
|
||||
case Kiloparsec:
|
||||
scale = static_cast<float>(1e3 * PARSEC);
|
||||
break;
|
||||
case Megaparsec:
|
||||
scale = static_cast<float>(1e6 * PARSEC);
|
||||
break;
|
||||
case Gigaparsec:
|
||||
scale = static_cast<float>(1e9 * PARSEC);
|
||||
break;
|
||||
case GigalightYears:
|
||||
scale = static_cast<float>(306391534.73091 * PARSEC);
|
||||
break;
|
||||
}
|
||||
const double scale = unitToMeter(_unit);
|
||||
|
||||
float fadeInVariable = 1.f;
|
||||
if (!_disableFadeInDistance) {
|
||||
float distCamera = static_cast<float>(glm::length(data.camera.positionVec3()));
|
||||
distCamera /= scale;
|
||||
distCamera = static_cast<float>(distCamera / scale);
|
||||
const glm::vec2 fadeRange = _fadeInDistance;
|
||||
//const float a = 1.f / ((fadeRange.y - fadeRange.x) * scale);
|
||||
const float a = 1.f / ((fadeRange.y - fadeRange.x));
|
||||
@@ -1095,16 +1072,37 @@ bool RenderablePlanesCloud::saveCachedFile(const std::string& file) const {
|
||||
}
|
||||
}
|
||||
|
||||
double RenderablePlanesCloud::unitToMeter(Unit unit) const {
|
||||
switch (_unit) {
|
||||
case Meter: return 1.0;
|
||||
case Kilometer: return 1e3;
|
||||
case Parsec: return PARSEC;
|
||||
case Kiloparsec: return 1000 * PARSEC;
|
||||
case Megaparsec: return 1e6 * PARSEC;
|
||||
case Gigaparsec: return 1e9 * PARSEC;
|
||||
case GigalightYears: return 306391534.73091 * PARSEC;
|
||||
default: throw ghoul::MissingCaseException();
|
||||
}
|
||||
}
|
||||
|
||||
void RenderablePlanesCloud::createPlanes() {
|
||||
if (_dataIsDirty && _hasSpeckFile) {
|
||||
const double scale = unitToMeter(_unit);
|
||||
|
||||
LDEBUG("Creating planes...");
|
||||
float maxSize = 0.f;
|
||||
double maxRadius = 0.0;
|
||||
for (size_t p = 0; p < _fullData.size(); p += _nValuesPerAstronomicalObject) {
|
||||
const glm::vec4 transformedPos = glm::vec4(
|
||||
_transformationMatrix *
|
||||
glm::dvec4(_fullData[p + 0], _fullData[p + 1], _fullData[p + 2], 1.0)
|
||||
);
|
||||
|
||||
const double r = glm::length(glm::dvec3(transformedPos) * scale);
|
||||
if (r > maxRadius) {
|
||||
maxRadius = r;
|
||||
}
|
||||
|
||||
// Plane vectors u and v
|
||||
glm::vec4 u = glm::vec4(
|
||||
_transformationMatrix *
|
||||
@@ -1145,31 +1143,6 @@ void RenderablePlanesCloud::createPlanes() {
|
||||
glm::vec4 vertex2 = transformedPos - u + v;
|
||||
glm::vec4 vertex4 = transformedPos + u - v;
|
||||
|
||||
float scale = 0.f;
|
||||
switch (_unit) {
|
||||
case Meter:
|
||||
scale = 1.f;
|
||||
break;
|
||||
case Kilometer:
|
||||
scale = 1e3f;
|
||||
break;
|
||||
case Parsec:
|
||||
scale = static_cast<float>(PARSEC);
|
||||
break;
|
||||
case Kiloparsec:
|
||||
scale = static_cast<float>(1e3 * PARSEC);
|
||||
break;
|
||||
case Megaparsec:
|
||||
scale = static_cast<float>(1e6 * PARSEC);
|
||||
break;
|
||||
case Gigaparsec:
|
||||
scale = static_cast<float>(1e9 * PARSEC);
|
||||
break;
|
||||
case GigalightYears:
|
||||
scale = static_cast<float>(306391534.73091 * PARSEC);
|
||||
break;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
maxSize = std::max(maxSize, vertex0[i]);
|
||||
maxSize = std::max(maxSize, vertex1[i]);
|
||||
@@ -1252,6 +1225,7 @@ void RenderablePlanesCloud::createPlanes() {
|
||||
|
||||
_dataIsDirty = false;
|
||||
|
||||
setBoundingSphere(maxRadius * _scaleFactor);
|
||||
_fadeInDistance.setMaxValue(glm::vec2(10.f * maxSize));
|
||||
}
|
||||
|
||||
|
||||
@@ -80,6 +80,7 @@ private:
|
||||
Gigaparsec = 5,
|
||||
GigalightYears = 6
|
||||
};
|
||||
double unitToMeter(Unit unit) const;
|
||||
|
||||
struct PlaneAggregate {
|
||||
int textureIndex;
|
||||
|
||||
@@ -170,6 +170,7 @@ RenderablePoints::RenderablePoints(const ghoul::Dictionary& dictionary)
|
||||
}
|
||||
|
||||
_pointColor = p.color;
|
||||
_pointColor.setViewOption(properties::Property::ViewOptions::Color);
|
||||
addProperty(_pointColor);
|
||||
|
||||
if (p.texture.has_value()) {
|
||||
|
||||
@@ -544,12 +544,12 @@ RenderableGlobe::RenderableGlobe(const ghoul::Dictionary& dictionary)
|
||||
if (p.radii.has_value()) {
|
||||
if (std::holds_alternative<glm::dvec3>(*p.radii)) {
|
||||
_ellipsoid = Ellipsoid(std::get<glm::dvec3>(*p.radii));
|
||||
setBoundingSphere(static_cast<float>(_ellipsoid.maximumRadius()));
|
||||
setBoundingSphere(_ellipsoid.maximumRadius());
|
||||
}
|
||||
else if (std::holds_alternative<double>(*p.radii)) {
|
||||
const double radius = std::get<double>(*p.radii);
|
||||
_ellipsoid = Ellipsoid({ radius, radius, radius });
|
||||
setBoundingSphere(static_cast<float>(_ellipsoid.maximumRadius()));
|
||||
setBoundingSphere(_ellipsoid.maximumRadius());
|
||||
}
|
||||
else {
|
||||
throw ghoul::MissingCaseException();
|
||||
@@ -843,9 +843,14 @@ void RenderableGlobe::update(const UpdateData& data) {
|
||||
);
|
||||
}
|
||||
|
||||
setBoundingSphere(static_cast<float>(
|
||||
_ellipsoid.maximumRadius() * glm::compMax(data.modelTransform.scale)
|
||||
));
|
||||
double bs = _ellipsoid.maximumRadius() * glm::compMax(data.modelTransform.scale);
|
||||
if (_hasRings) {
|
||||
const double ringSize = _ringsComponent.size();
|
||||
if (ringSize > bs) {
|
||||
bs = ringSize;
|
||||
}
|
||||
}
|
||||
setBoundingSphere(bs);
|
||||
|
||||
glm::dmat4 translation =
|
||||
glm::translate(glm::dmat4(1.0), data.modelTransform.translation);
|
||||
@@ -1831,7 +1836,7 @@ SurfacePositionHandle RenderableGlobe::calculateSurfacePositionHandle(
|
||||
double heightToSurface = getHeight(targetModelSpace);
|
||||
heightToSurface = glm::isnan(heightToSurface) ? 0.0 : heightToSurface;
|
||||
centerToEllipsoidSurface = glm::isnan(glm::length(centerToEllipsoidSurface)) ?
|
||||
(glm::dvec3(0.0, 1.0, 0.0) * static_cast<double>(boundingSphere())) :
|
||||
(glm::dvec3(0.0, 1.0, 0.0) * interactionSphere()) :
|
||||
centerToEllipsoidSurface;
|
||||
ellipsoidSurfaceOutDirection = glm::isnan(glm::length(ellipsoidSurfaceOutDirection)) ?
|
||||
glm::dvec3(0.0, 1.0, 0.0) : ellipsoidSurfaceOutDirection;
|
||||
|
||||
@@ -56,14 +56,14 @@ namespace {
|
||||
|
||||
constexpr const std::array<const char*, 9> UniformNames = {
|
||||
"modelViewProjectionMatrix", "textureOffset", "colorFilterValue", "_nightFactor",
|
||||
"sunPosition", "ringTexture", "shadowMatrix", "shadowMapTexture",
|
||||
"sunPosition", "ringTexture", "shadowMatrix", "shadowMapTexture",
|
||||
"zFightingPercentage"
|
||||
};
|
||||
|
||||
constexpr const std::array<const char*, 15> UniformNamesAdvancedRings = {
|
||||
"modelViewProjectionMatrix", "textureOffset", "colorFilterValue", "_nightFactor",
|
||||
"sunPosition", "sunPositionObj", "camPositionObj", "ringTextureFwrd",
|
||||
"ringTextureBckwrd", "ringTextureUnlit", "ringTextureColor",
|
||||
"sunPosition", "sunPositionObj", "camPositionObj", "ringTextureFwrd",
|
||||
"ringTextureBckwrd", "ringTextureUnlit", "ringTextureColor",
|
||||
"ringTextureTransparency", "shadowMatrix", "shadowMapTexture", "zFightingPercentage"
|
||||
};
|
||||
|
||||
@@ -251,6 +251,7 @@ void RingsComponent::initialize() {
|
||||
|
||||
addProperty(_enabled);
|
||||
|
||||
_size.setViewOption(properties::Property::ViewOptions::Logarithmic);
|
||||
_size = p.size.value_or(_size);
|
||||
_size.onChange([&]() { _planeIsDirty = true; });
|
||||
addProperty(_size);
|
||||
@@ -262,7 +263,7 @@ void RingsComponent::initialize() {
|
||||
addProperty(_texturePath);
|
||||
_textureFile->setCallback([&](const File&) { _textureIsDirty = true; });
|
||||
}
|
||||
|
||||
|
||||
if (p.textureFwrd.has_value()) {
|
||||
_textureFwrdPath = absPath(p.textureFwrd->string());
|
||||
_textureFileForwards = std::make_unique<File>(_textureFwrdPath);
|
||||
@@ -423,11 +424,11 @@ void RingsComponent::draw(const RenderData& data,
|
||||
);
|
||||
|
||||
_shader->setUniform(
|
||||
_uniformCacheAdvancedRings.sunPositionObj,
|
||||
_uniformCacheAdvancedRings.sunPositionObj,
|
||||
sunPositionObjectSpace
|
||||
);
|
||||
_shader->setUniform(
|
||||
_uniformCacheAdvancedRings.zFightingPercentage,
|
||||
_uniformCacheAdvancedRings.zFightingPercentage,
|
||||
_zFightingPercentage
|
||||
);
|
||||
_shader->setUniform(
|
||||
@@ -438,21 +439,21 @@ void RingsComponent::draw(const RenderData& data,
|
||||
ringTextureFwrdUnit.activate();
|
||||
_textureForwards->bind();
|
||||
_shader->setUniform(
|
||||
_uniformCacheAdvancedRings.ringTextureFwrd,
|
||||
_uniformCacheAdvancedRings.ringTextureFwrd,
|
||||
ringTextureFwrdUnit
|
||||
);
|
||||
|
||||
ringTextureBckwrdUnit.activate();
|
||||
_textureBackwards->bind();
|
||||
_shader->setUniform(
|
||||
_uniformCacheAdvancedRings.ringTextureBckwrd,
|
||||
_uniformCacheAdvancedRings.ringTextureBckwrd,
|
||||
ringTextureBckwrdUnit
|
||||
);
|
||||
|
||||
ringTextureUnlitUnit.activate();
|
||||
_textureUnlit->bind();
|
||||
_shader->setUniform(
|
||||
_uniformCacheAdvancedRings.ringTextureUnlit,
|
||||
_uniformCacheAdvancedRings.ringTextureUnlit,
|
||||
ringTextureUnlitUnit
|
||||
);
|
||||
|
||||
@@ -488,7 +489,7 @@ void RingsComponent::draw(const RenderData& data,
|
||||
);
|
||||
|
||||
_shader->setUniform(
|
||||
_uniformCacheAdvancedRings.camPositionObj,
|
||||
_uniformCacheAdvancedRings.camPositionObj,
|
||||
_camPositionObjectSpace
|
||||
);
|
||||
|
||||
@@ -513,7 +514,7 @@ void RingsComponent::draw(const RenderData& data,
|
||||
_shader->setUniform(_uniformCache.sunPosition, _sunPosition);
|
||||
_shader->setUniform(_uniformCache.zFightingPercentage, _zFightingPercentage);
|
||||
_shader->setUniform(
|
||||
_uniformCache.modelViewProjectionMatrix,
|
||||
_uniformCache.modelViewProjectionMatrix,
|
||||
modelViewProjectionTransform
|
||||
);
|
||||
|
||||
@@ -533,7 +534,7 @@ void RingsComponent::draw(const RenderData& data,
|
||||
shadowMapUnit.activate();
|
||||
glBindTexture(GL_TEXTURE_2D, shadowData.shadowDepthTexture);
|
||||
_shader->setUniform(_uniformCache.shadowMapTexture, shadowMapUnit);
|
||||
}
|
||||
}
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnablei(GL_BLEND, 0);
|
||||
@@ -831,7 +832,7 @@ void RingsComponent::compileShadowShader() {
|
||||
|
||||
// Uses multiple textures for the Rings
|
||||
// See https://bjj.mmedia.is/data/s_rings/index.html for theory behind it
|
||||
if (_isAdvancedTextureEnabled) {
|
||||
if (_isAdvancedTextureEnabled) {
|
||||
_shader = global::renderEngine->buildRenderProgram(
|
||||
"AdvancedRingsProgram",
|
||||
absPath("${MODULE_GLOBEBROWSING}/shaders/advanced_rings_vs.glsl"),
|
||||
@@ -840,8 +841,8 @@ void RingsComponent::compileShadowShader() {
|
||||
);
|
||||
|
||||
ghoul::opengl::updateUniformLocations(
|
||||
*_shader,
|
||||
_uniformCacheAdvancedRings,
|
||||
*_shader,
|
||||
_uniformCacheAdvancedRings,
|
||||
UniformNamesAdvancedRings
|
||||
);
|
||||
}
|
||||
@@ -866,4 +867,8 @@ bool RingsComponent::isEnabled() const {
|
||||
return _enabled;
|
||||
}
|
||||
|
||||
double RingsComponent::size() const {
|
||||
return _size;
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -71,6 +71,7 @@ public:
|
||||
static documentation::Documentation Documentation();
|
||||
|
||||
bool isEnabled() const;
|
||||
double size() const;
|
||||
|
||||
private:
|
||||
void loadTexture();
|
||||
|
||||
@@ -115,9 +115,17 @@ bool DataCygnet::updateTexture() {
|
||||
}
|
||||
|
||||
bool texturesReady = false;
|
||||
const std::vector<int>& selectedOptions = _dataOptions.value();
|
||||
const std::set<std::string>& selectedOptions = _dataOptions;
|
||||
const std::vector<std::string>& options = _dataOptions.options();
|
||||
std::vector<int> selectedOptionsIndices;
|
||||
for (const std::string& option : selectedOptions) {
|
||||
auto it = std::find(options.begin(), options.end(), option);
|
||||
ghoul_assert(it != options.end(), "Selected option must be in all options");
|
||||
int idx = static_cast<int>(std::distance(options.begin(), it));
|
||||
selectedOptionsIndices.push_back(idx);
|
||||
}
|
||||
|
||||
for (int option : selectedOptions) {
|
||||
for (int option : selectedOptionsIndices) {
|
||||
float* values = data[option];
|
||||
if (!values) {
|
||||
continue;
|
||||
@@ -191,7 +199,16 @@ bool DataCygnet::readyToRender() const {
|
||||
* ghoul::TextureUnit needs to be passed as an argument to both.
|
||||
*/
|
||||
void DataCygnet::setTextureUniforms() {
|
||||
const std::vector<int>& selectedOptions = _dataOptions.value();
|
||||
const std::set<std::string>& selectedOptions = _dataOptions;
|
||||
const std::vector<std::string>& options = _dataOptions.options();
|
||||
std::vector<int> selectedOptionsIndices;
|
||||
for (const std::string& option : selectedOptions) {
|
||||
auto it = std::find(options.begin(), options.end(), option);
|
||||
ghoul_assert(it != options.end(), "Selected option must be in all options");
|
||||
int idx = static_cast<int>(std::distance(options.begin(), it));
|
||||
selectedOptionsIndices.push_back(idx);
|
||||
}
|
||||
|
||||
int activeTextures = std::min(static_cast<int>(selectedOptions.size()), MaxTextures);
|
||||
int activeTransferfunctions = std::min(
|
||||
static_cast<int>(_transferFunctions.size()),
|
||||
@@ -201,7 +218,7 @@ void DataCygnet::setTextureUniforms() {
|
||||
// Set Textures
|
||||
ghoul::opengl::TextureUnit txUnits[MaxTextures];
|
||||
int j = 0;
|
||||
for (int option : selectedOptions) {
|
||||
for (int option : selectedOptionsIndices) {
|
||||
if (_textures[option]) {
|
||||
txUnits[j].activate();
|
||||
_textures[option]->bind();
|
||||
@@ -215,7 +232,7 @@ void DataCygnet::setTextureUniforms() {
|
||||
}
|
||||
|
||||
if (activeTextures > 0 &&
|
||||
selectedOptions.back() >= static_cast<int>(_transferFunctions.size()))
|
||||
selectedOptionsIndices.back() >= static_cast<int>(_transferFunctions.size()))
|
||||
{
|
||||
activeTransferfunctions = 1;
|
||||
}
|
||||
@@ -230,7 +247,7 @@ void DataCygnet::setTextureUniforms() {
|
||||
_shader->setUniform("transferFunctions[0]", tfUnits[0]);
|
||||
}
|
||||
else {
|
||||
for (int option : selectedOptions) {
|
||||
for (int option : selectedOptionsIndices) {
|
||||
if (static_cast<int>(_transferFunctions.size()) >= option) {
|
||||
tfUnits[j].activate();
|
||||
_transferFunctions[option].bind();
|
||||
@@ -277,7 +294,7 @@ void DataCygnet::fillOptions(const std::string& source) {
|
||||
);
|
||||
|
||||
for (int i = 0; i < static_cast<int>(options.size()); i++) {
|
||||
_dataOptions.addOption({ i, options[i] });
|
||||
_dataOptions.addOption(options[i]);
|
||||
_textures.push_back(nullptr);
|
||||
}
|
||||
|
||||
@@ -288,7 +305,7 @@ void DataCygnet::fillOptions(const std::string& source) {
|
||||
_dataOptions.setValue(g->dataOptionsValue());
|
||||
}
|
||||
else {
|
||||
_dataOptions.setValue(std::vector<int>(1, 0));
|
||||
_dataOptions.setValue({ options.front() });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -332,7 +349,13 @@ void DataCygnet::subscribeToGroup() {
|
||||
[&](const ghoul::Dictionary& dict) {
|
||||
LDEBUG(identifier() + " Event dataOptionsChanged");
|
||||
if (dict.hasValue<std::vector<int>>("dataOptions")) {
|
||||
_dataOptions = dict.value<std::vector<int>>("dataOptions");
|
||||
std::vector<int> idx = dict.value<std::vector<int>>("dataOptions");
|
||||
std::vector<std::string> opts = _dataOptions.options();
|
||||
std::set<std::string> selected;
|
||||
for (int i : idx) {
|
||||
selected.insert(opts[i]);
|
||||
}
|
||||
_dataOptions = selected;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
@@ -166,23 +166,23 @@ void IswaDataGroup::registerProperties() {
|
||||
_dataOptions.onChange([this]() {
|
||||
LDEBUG("Group " + identifier() + " published dataOptionsChanged");
|
||||
ghoul::Dictionary dict;
|
||||
dict.setValue("dataOptions", _dataOptions.value());
|
||||
std::set<std::string> set = _dataOptions;
|
||||
std::vector<std::string> vec(set.begin(), set.end());
|
||||
dict.setValue("dataOptions", vec);
|
||||
_groupEvent.publish("dataOptionsChanged", dict);
|
||||
});
|
||||
}
|
||||
|
||||
void IswaDataGroup::registerOptions(
|
||||
const std::vector<properties::SelectionProperty::Option>& options)
|
||||
{
|
||||
void IswaDataGroup::registerOptions(const std::vector<std::string>& options) {
|
||||
if (!_registered) {
|
||||
registerProperties();
|
||||
}
|
||||
|
||||
if (_dataOptions.options().empty()) {
|
||||
for (properties::SelectionProperty::Option option : options) {
|
||||
_dataOptions.addOption({ option.value, option.description });
|
||||
for (const std::string& option : options) {
|
||||
_dataOptions.addOption(option);
|
||||
}
|
||||
_dataOptions.setValue(std::vector<int>(1, 0));
|
||||
_dataOptions.setValue({ options.front() });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,7 +198,7 @@ void IswaDataGroup::createDataProcessor() {
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<int> IswaDataGroup::dataOptionsValue() const {
|
||||
std::set<std::string> IswaDataGroup::dataOptionsValue() const {
|
||||
return _dataOptions;
|
||||
}
|
||||
|
||||
|
||||
@@ -38,9 +38,8 @@ public:
|
||||
IswaDataGroup(std::string name, std::string type);
|
||||
~IswaDataGroup();
|
||||
|
||||
void registerOptions(
|
||||
const std::vector<properties::SelectionProperty::Option>& options);
|
||||
std::vector<int> dataOptionsValue() const;
|
||||
void registerOptions(const std::vector<std::string>& options);
|
||||
std::set<std::string> dataOptionsValue() const;
|
||||
|
||||
protected:
|
||||
void registerProperties();
|
||||
|
||||
@@ -67,7 +67,7 @@ void IswaKameleonGroup::clearGroup() {
|
||||
clearFieldlines();
|
||||
}
|
||||
|
||||
std::vector<int> IswaKameleonGroup::fieldlineValue() const {
|
||||
std::set<std::string> IswaKameleonGroup::fieldlineValue() const {
|
||||
return _fieldlines;
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ void IswaKameleonGroup::readFieldlinePaths(const std::string& indexFile) {
|
||||
int i = 0;
|
||||
|
||||
for (json::iterator it = fieldlines.begin(); it != fieldlines.end(); ++it) {
|
||||
_fieldlines.addOption({ i, it.key() });
|
||||
_fieldlines.addOption(it.key());
|
||||
_fieldlineState[i] = std::make_tuple<std::string, std::string, bool>(
|
||||
identifier() + "/" + it.key(),
|
||||
it.value(),
|
||||
@@ -137,14 +137,16 @@ void IswaKameleonGroup::readFieldlinePaths(const std::string& indexFile) {
|
||||
}
|
||||
|
||||
void IswaKameleonGroup::updateFieldlineSeeds() {
|
||||
const std::vector<int>& options = _fieldlines.value();
|
||||
const std::set<std::string>& options = _fieldlines;
|
||||
std::vector<std::string> opts = _fieldlines.options();
|
||||
|
||||
// SeedPath == map<int selectionValue, tuple<string name, string path, bool active>>
|
||||
using K = int;
|
||||
using V = std::tuple<std::string, std::string, bool>;
|
||||
for (std::pair<const K, V>& seedPath : _fieldlineState) {
|
||||
// if this option was turned off
|
||||
const auto it = std::find(options.begin(), options.end(), seedPath.first);
|
||||
std::string o = opts[seedPath.first];
|
||||
const auto it = std::find(options.begin(), options.end(), o);
|
||||
if (it == options.end() && std::get<2>(seedPath.second)) {
|
||||
LDEBUG("Removed fieldlines: " + std::get<0>(seedPath.second));
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ public:
|
||||
|
||||
virtual void clearGroup() override;
|
||||
|
||||
std::vector<int> fieldlineValue() const;
|
||||
std::set<std::string> fieldlineValue() const;
|
||||
void setFieldlineInfo(std::string fieldlineIndexFile, std::string kameleonPath);
|
||||
void changeCdf(std::string path);
|
||||
|
||||
|
||||
@@ -112,7 +112,7 @@ KameleonPlane::~KameleonPlane() {}
|
||||
|
||||
void KameleonPlane::deinitializeGL() {
|
||||
IswaCygnet::deinitialize();
|
||||
_fieldlines = std::vector<int>();
|
||||
_fieldlines = std::set<std::string>();
|
||||
}
|
||||
|
||||
void KameleonPlane::initializeGL() {
|
||||
@@ -268,16 +268,16 @@ void KameleonPlane::setUniforms() {
|
||||
}
|
||||
|
||||
void KameleonPlane::updateFieldlineSeeds() {
|
||||
std::vector<int> selectedOptions = _fieldlines.value();
|
||||
std::set<std::string> selectedOptions = _fieldlines;
|
||||
std::vector<std::string> opts = _fieldlines.options();
|
||||
|
||||
// seedPath == map<int selectionValue, tuple<string name, string path, bool active>>
|
||||
for (auto& seedPath : _fieldlineState) {
|
||||
using K = int;
|
||||
using V = std::tuple<std::string, std::string, bool>;
|
||||
for (std::pair<const K, V>& seedPath : _fieldlineState) {
|
||||
// if this option was turned off
|
||||
const auto it = std::find(
|
||||
selectedOptions.begin(),
|
||||
selectedOptions.end(),
|
||||
seedPath.first
|
||||
);
|
||||
std::string o = opts[seedPath.first];
|
||||
const auto it = std::find(selectedOptions.begin(), selectedOptions.end(), o);
|
||||
if (it == selectedOptions.end() && std::get<2>(seedPath.second)) {
|
||||
SceneGraphNode* n = global::renderEngine->scene()->sceneGraphNode(
|
||||
std::get<0>(seedPath.second)
|
||||
@@ -336,7 +336,7 @@ void KameleonPlane::readFieldlinePaths(const std::string& indexFile) {
|
||||
const std::string& fullName = identifier();
|
||||
std::string partName = fullName.substr(0,fullName.find_last_of("-"));
|
||||
for (json::iterator it = fieldlines.begin(); it != fieldlines.end(); ++it) {
|
||||
_fieldlines.addOption({i, it.key()});
|
||||
_fieldlines.addOption(it.key());
|
||||
_fieldlineState[i] = std::make_tuple<std::string, std::string, bool>(
|
||||
partName + "/" + it.key(),
|
||||
it.value(),
|
||||
|
||||
@@ -73,11 +73,10 @@ void DataProcessorJson::addDataValues(const std::string& data,
|
||||
|
||||
std::vector<float> sum(numOptions, 0.f);
|
||||
std::vector<std::vector<float>> optionValues(numOptions, std::vector<float>());
|
||||
const std::vector<properties::SelectionProperty::Option>& options =
|
||||
dataOptions.options();
|
||||
const std::vector<std::string>& options = dataOptions.options();
|
||||
|
||||
for (int i = 0; i < numOptions; ++i) {
|
||||
const json& row = variables[options[i].description];
|
||||
const json& row = variables[options[i]];
|
||||
// int rowsize = row.size();
|
||||
|
||||
for (size_t y = 0; y < row.size(); ++y) {
|
||||
@@ -108,18 +107,23 @@ std::vector<float*> DataProcessorJson::processData(const std::string& data,
|
||||
const json& j = json::parse(data);
|
||||
json variables = j["variables"];
|
||||
|
||||
const std::vector<int>& selectedOptions = optionProp;
|
||||
|
||||
const std::vector<properties::SelectionProperty::Option>& options =
|
||||
optionProp.options();
|
||||
const std::set<std::string>& selectedOptions = optionProp;
|
||||
const std::vector<std::string>& options = optionProp.options();
|
||||
std::vector<int> selectedOptionsIndices;
|
||||
for (const std::string& option : selectedOptions) {
|
||||
auto it = std::find(options.begin(), options.end(), option);
|
||||
ghoul_assert(it != options.end(), "Selected option must be in all options");
|
||||
int idx = static_cast<int>(std::distance(options.begin(), it));
|
||||
selectedOptionsIndices.push_back(idx);
|
||||
}
|
||||
|
||||
std::vector<float*> dataOptions(options.size(), nullptr);
|
||||
for (int option : selectedOptions) {
|
||||
for (int option : selectedOptionsIndices) {
|
||||
// @CLEANUP: This memory is very easy to lose and should be replaced by some
|
||||
// other mechanism (std::vector<float> most likely)
|
||||
dataOptions[option] = new float[dimensions.x * dimensions.y] { 0.f };
|
||||
|
||||
json row = variables[options[option].description];
|
||||
json row = variables[options[option]];
|
||||
const int rowsize = static_cast<int>(row.size());
|
||||
|
||||
for (int y = 0; y < rowsize; ++y) {
|
||||
@@ -135,7 +139,7 @@ std::vector<float*> DataProcessorJson::processData(const std::string& data,
|
||||
}
|
||||
}
|
||||
|
||||
calculateFilterValues(selectedOptions);
|
||||
calculateFilterValues(selectedOptionsIndices);
|
||||
return dataOptions;
|
||||
}
|
||||
|
||||
|
||||
@@ -80,15 +80,14 @@ void DataProcessorKameleon::addDataValues(const std::string& path,
|
||||
|
||||
std::vector<float> sum(numOptions, 0.f);
|
||||
std::vector<std::vector<float>> optionValues(numOptions, std::vector<float>());
|
||||
const std::vector<properties::SelectionProperty::Option>& options =
|
||||
dataOptions.options();
|
||||
const std::vector<std::string>& options = dataOptions.options();
|
||||
|
||||
const int numValues = static_cast<int>(_dimensions.x * _dimensions.y * _dimensions.z);
|
||||
|
||||
for (int i = 0; i < numOptions; ++i) {
|
||||
//0.5 to gather interesting values for the normalization/histograms.
|
||||
float* values = _kw->uniformSliceValues(
|
||||
options[i].description,
|
||||
options[i],
|
||||
_dimensions,
|
||||
0.5f
|
||||
);
|
||||
@@ -120,17 +119,22 @@ std::vector<float*> DataProcessorKameleon::processData(const std::string& path,
|
||||
initializeKameleonWrapper(path);
|
||||
}
|
||||
|
||||
const std::vector<int>& selectedOptions = optionProp;
|
||||
|
||||
const std::vector<properties::SelectionProperty::Option>& options =
|
||||
optionProp.options();
|
||||
const std::set<std::string>& selectedOptions = optionProp;
|
||||
const std::vector<std::string>& options = optionProp.options();
|
||||
std::vector<int> selectedOptionsIndices;
|
||||
for (const std::string& option : selectedOptions) {
|
||||
auto it = std::find(options.begin(), options.end(), option);
|
||||
ghoul_assert(it != options.end(), "Selected option must be in all options");
|
||||
int idx = static_cast<int>(std::distance(options.begin(), it));
|
||||
selectedOptionsIndices.push_back(idx);
|
||||
}
|
||||
|
||||
const int numValues = static_cast<int>(glm::compMul(dimensions));
|
||||
|
||||
std::vector<float*> dataOptions(numOptions, nullptr);
|
||||
for (int option : selectedOptions) {
|
||||
for (int option : selectedOptionsIndices) {
|
||||
dataOptions[option] = _kw->uniformSliceValues(
|
||||
options[option].description,
|
||||
options[option],
|
||||
dimensions,
|
||||
_slice
|
||||
);
|
||||
@@ -141,7 +145,7 @@ std::vector<float*> DataProcessorKameleon::processData(const std::string& path,
|
||||
}
|
||||
}
|
||||
|
||||
calculateFilterValues(selectedOptions);
|
||||
calculateFilterValues(selectedOptionsIndices);
|
||||
return dataOptions;
|
||||
}
|
||||
|
||||
|
||||
@@ -142,6 +142,10 @@ std::vector<float*> DataProcessorText::processData(const std::string& data,
|
||||
properties::SelectionProperty& options,
|
||||
glm::size3_t& dimensions)
|
||||
{
|
||||
// The update of the selection properties broke this and we don't have the data to
|
||||
// actually test whether this update works. So if you are getting a crash around here
|
||||
// this is why
|
||||
|
||||
if (data.empty()) {
|
||||
return std::vector<float*>();
|
||||
}
|
||||
@@ -149,11 +153,20 @@ std::vector<float*> DataProcessorText::processData(const std::string& data,
|
||||
std::string line;
|
||||
std::stringstream memorystream(data);
|
||||
|
||||
const std::vector<int>& selectedOptions = options.value();
|
||||
const std::set<std::string>& selectedOptions = options.value();
|
||||
const std::vector<std::string>& allOptions = options.options();
|
||||
std::vector<int> selectedOptionsIndices;
|
||||
|
||||
std::vector<float*> dataOptions(options.options().size(), nullptr);
|
||||
for (int o : selectedOptions) {
|
||||
dataOptions[o] = new float[dimensions.x * dimensions.y] { 0.f };
|
||||
for (const std::string& o : selectedOptions) {
|
||||
auto it = std::find(allOptions.begin(), allOptions.end(), o);
|
||||
ghoul_assert(
|
||||
it != allOptions.end(),
|
||||
"Selected option must be in list of all options"
|
||||
);
|
||||
int idx = static_cast<int>(std::distance(allOptions.begin(), it));
|
||||
selectedOptionsIndices.push_back(idx);
|
||||
dataOptions[idx] = new float[dimensions.x * dimensions.y] { 0.f };
|
||||
}
|
||||
|
||||
int numValues = 0;
|
||||
@@ -172,11 +185,11 @@ std::vector<float*> DataProcessorText::processData(const std::string& data,
|
||||
last = (last > 0)? last : lineSize;
|
||||
|
||||
const auto it = std::find(
|
||||
selectedOptions.begin(),
|
||||
selectedOptions.end(),
|
||||
selectedOptionsIndices.begin(),
|
||||
selectedOptionsIndices.end(),
|
||||
option
|
||||
);
|
||||
if (option >= 0 && it != selectedOptions.end()) {
|
||||
if (option >= 0 && it != selectedOptionsIndices.end()) {
|
||||
const float value = std::stof(line.substr(first, last));
|
||||
dataOptions[option][numValues] = processDataPoint(value, option);
|
||||
}
|
||||
@@ -187,9 +200,10 @@ std::vector<float*> DataProcessorText::processData(const std::string& data,
|
||||
numValues++;
|
||||
}
|
||||
|
||||
calculateFilterValues(selectedOptions);
|
||||
calculateFilterValues(selectedOptionsIndices);
|
||||
|
||||
return dataOptions;
|
||||
//#endif
|
||||
}
|
||||
|
||||
} //namespace openspace
|
||||
|
||||
@@ -143,6 +143,7 @@ RenderableHabitableZone::RenderableHabitableZone(const ghoul::Dictionary& dictio
|
||||
_width.setReadOnly(true);
|
||||
|
||||
computeZone();
|
||||
setBoundingSphere(_size);
|
||||
}
|
||||
|
||||
void RenderableHabitableZone::render(const RenderData& data, RendererTasks&) {
|
||||
|
||||
@@ -476,6 +476,14 @@ void RenderableOrbitalKepler::initializeGL() {
|
||||
_uniformCache.opacity = _programObject->uniformLocation("opacity");
|
||||
|
||||
updateBuffers();
|
||||
|
||||
double maxSemiMajorAxis = 0.0;
|
||||
for (const KeplerParameters& kp : _data) {
|
||||
if (kp.semiMajorAxis > maxSemiMajorAxis) {
|
||||
maxSemiMajorAxis = kp.semiMajorAxis;
|
||||
}
|
||||
}
|
||||
setBoundingSphere(maxSemiMajorAxis * 1000);
|
||||
}
|
||||
|
||||
void RenderableOrbitalKepler::deinitializeGL() {
|
||||
|
||||
@@ -1486,14 +1486,21 @@ void RenderableStars::createDataSlice(ColorOption option) {
|
||||
-std::numeric_limits<float>::max()
|
||||
);
|
||||
|
||||
double maxRadius = 0.0;
|
||||
|
||||
for (size_t i = 0; i < _fullData.size(); i += _nValuesPerStar) {
|
||||
glm::vec3 position = glm::vec3(
|
||||
glm::dvec3 position = glm::dvec3(
|
||||
_fullData[i + 0],
|
||||
_fullData[i + 1],
|
||||
_fullData[i + 2]
|
||||
);
|
||||
position *= openspace::distanceconstants::Parsec;
|
||||
|
||||
const double r = glm::length(position);
|
||||
if (r > maxRadius) {
|
||||
maxRadius = r;
|
||||
}
|
||||
|
||||
switch (option) {
|
||||
case ColorOption::Color:
|
||||
case ColorOption::FixedColor:
|
||||
@@ -1503,7 +1510,11 @@ void RenderableStars::createDataSlice(ColorOption option) {
|
||||
std::array<float, sizeof(ColorVBOLayout) / sizeof(float)> data;
|
||||
} layout;
|
||||
|
||||
layout.value.position = { { position[0], position[1], position[2] } };
|
||||
layout.value.position = { {
|
||||
static_cast<float>(position[0]),
|
||||
static_cast<float>(position[1]),
|
||||
static_cast<float>(position[2])
|
||||
}};
|
||||
|
||||
if (_enableTestGrid) {
|
||||
float sunColor = 0.650f;
|
||||
@@ -1531,7 +1542,11 @@ void RenderableStars::createDataSlice(ColorOption option) {
|
||||
std::array<float, sizeof(VelocityVBOLayout) / sizeof(float)> data;
|
||||
} layout;
|
||||
|
||||
layout.value.position = { { position[0], position[1], position[2] } };
|
||||
layout.value.position = {{
|
||||
static_cast<float>(position[0]),
|
||||
static_cast<float>(position[1]),
|
||||
static_cast<float>(position[2])
|
||||
}};
|
||||
|
||||
layout.value.value = _fullData[i + _bvColorArrayPos];
|
||||
layout.value.luminance = _fullData[i + _lumArrayPos];
|
||||
@@ -1556,7 +1571,11 @@ void RenderableStars::createDataSlice(ColorOption option) {
|
||||
std::array<float, sizeof(SpeedVBOLayout) / sizeof(float)> data;
|
||||
} layout;
|
||||
|
||||
layout.value.position = { { position[0], position[1], position[2] } };
|
||||
layout.value.position = {{
|
||||
static_cast<float>(position[0]),
|
||||
static_cast<float>(position[1]),
|
||||
static_cast<float>(position[2])
|
||||
}};
|
||||
|
||||
layout.value.value = _fullData[i + _bvColorArrayPos];
|
||||
layout.value.luminance = _fullData[i + _lumArrayPos];
|
||||
@@ -1579,7 +1598,11 @@ void RenderableStars::createDataSlice(ColorOption option) {
|
||||
std::array<float, sizeof(OtherDataLayout)> data;
|
||||
} layout = {};
|
||||
|
||||
layout.value.position = { { position[0], position[1], position[2] } };
|
||||
layout.value.position = {{
|
||||
static_cast<float>(position[0]),
|
||||
static_cast<float>(position[1]),
|
||||
static_cast<float>(position[2])
|
||||
}};
|
||||
|
||||
int index = _otherDataOption.value();
|
||||
// plus 3 because of the position
|
||||
@@ -1612,6 +1635,8 @@ void RenderableStars::createDataSlice(ColorOption option) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setBoundingSphere(maxRadius);
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -146,7 +146,7 @@ void gradient(double* g, double* par, int x, void* fdata, LMstat* lmstat) {
|
||||
FunctionData* ptr = reinterpret_cast<FunctionData*>(fdata);
|
||||
double f0 = distToMinimize(par, x, fdata, lmstat);
|
||||
// scale value to find minimum step size h, dependant on planet size
|
||||
double scale = log10(ptr->node->boundingSphere());
|
||||
double scale = log10(ptr->node->interactionSphere());
|
||||
std::vector<double> dPar(ptr->nDOF, 0.0);
|
||||
dPar.assign(par, par + ptr->nDOF);
|
||||
|
||||
|
||||
@@ -507,15 +507,15 @@ void TouchInteraction::findSelectedNode(const std::vector<TouchInputHolder>& lis
|
||||
size_t id = inputHolder.fingerId();
|
||||
|
||||
for (SceneGraphNode* node : selectableNodes) {
|
||||
double boundingSphereSquared = static_cast<double>(node->boundingSphere()) *
|
||||
static_cast<double>(node->boundingSphere());
|
||||
double interactionSphereSquared =
|
||||
node->interactionSphere() * node->interactionSphere();
|
||||
glm::dvec3 camToSelectable = node->worldPosition() - camPos;
|
||||
double intersectionDist = 0.0;
|
||||
const bool intersected = glm::intersectRaySphere(
|
||||
camPos,
|
||||
raytrace,
|
||||
node->worldPosition(),
|
||||
boundingSphereSquared,
|
||||
interactionSphereSquared,
|
||||
intersectionDist
|
||||
);
|
||||
if (intersected) {
|
||||
@@ -921,7 +921,7 @@ double TouchInteraction::computeTapZoomDistance(double zoomGain) {
|
||||
global::navigationHandler->orbitalNavigator().anchorNode()->worldPosition()
|
||||
);
|
||||
|
||||
dist -= anchor->boundingSphere();
|
||||
dist -= anchor->interactionSphere();
|
||||
|
||||
double newVelocity = dist * _tapZoomFactor;
|
||||
newVelocity *= std::max(_touchScreenSize.value() * 0.1, 1.0);
|
||||
@@ -962,9 +962,9 @@ void TouchInteraction::step(double dt, bool directTouch) {
|
||||
dquat globalCamRot = normalize(quat_cast(inverse(lookAtMat)));
|
||||
dquat localCamRot = inverse(globalCamRot) * _camera->rotationQuaternion();
|
||||
|
||||
const double boundingSphere = anchor->boundingSphere();
|
||||
const double distance = std::max(length(centerToCamera) - boundingSphere, 0.0);
|
||||
_currentRadius = boundingSphere /
|
||||
const double interactionSphere = anchor->interactionSphere();
|
||||
const double distance = std::max(length(centerToCamera) - interactionSphere, 0.0);
|
||||
_currentRadius = interactionSphere /
|
||||
std::max(distance * _projectionScaleFactor, 1.0);
|
||||
|
||||
{
|
||||
@@ -1010,7 +1010,7 @@ void TouchInteraction::step(double dt, bool directTouch) {
|
||||
|
||||
// This is a rough estimate of the node surface
|
||||
// If nobody has set another zoom in limit, use this as default zoom in bounds
|
||||
double zoomInBounds = boundingSphere * _zoomBoundarySphereMultiplier;
|
||||
double zoomInBounds = interactionSphere * _zoomBoundarySphereMultiplier;
|
||||
bool isZoomInLimitSet = (_zoomInLimit.value() >= 0.0);
|
||||
|
||||
if (isZoomInLimitSet && _zoomInLimit.value() < zoomInBounds) {
|
||||
@@ -1049,7 +1049,7 @@ void TouchInteraction::step(double dt, bool directTouch) {
|
||||
double zoomVelocity = _vel.zoom;
|
||||
if (!directTouch) {
|
||||
const double distanceFromSurface =
|
||||
length(currentPosDistance) - anchor->boundingSphere();
|
||||
length(currentPosDistance) - anchor->interactionSphere();
|
||||
if (distanceFromSurface > 0.1) {
|
||||
const double ratioOfDistanceToNodeVsSurf =
|
||||
length(currentPosDistance) / distanceFromSurface;
|
||||
|
||||
54
shaders/core/xyzuvrgba_fs.glsl
Normal file
54
shaders/core/xyzuvrgba_fs.glsl
Normal file
@@ -0,0 +1,54 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2021 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
|
||||
* software and associated documentation files (the "Software"), to deal in the Software *
|
||||
* without restriction, including without limitation the rights to use, copy, modify, *
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
|
||||
* permit persons to whom the Software is furnished to do so, subject to the following *
|
||||
* conditions: *
|
||||
* *
|
||||
* The above copyright notice and this permission notice shall be included in all copies *
|
||||
* or substantial portions of the Software. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#include "fragment.glsl"
|
||||
|
||||
uniform bool hasTexture = false;
|
||||
uniform bvec2 shouldFlipTexture = bvec2(false, false);
|
||||
uniform sampler2D tex;
|
||||
uniform vec4 color = vec4(1.0, 1.0, 1.0, 1.0);
|
||||
|
||||
in float depth;
|
||||
in vec2 out_uv;
|
||||
in vec4 out_color;
|
||||
|
||||
Fragment getFragment() {
|
||||
Fragment frag;
|
||||
|
||||
if (hasTexture) {
|
||||
vec2 uv = out_uv;
|
||||
if (shouldFlipTexture.x) {
|
||||
uv.x = 1.0 - uv.x;
|
||||
}
|
||||
if (shouldFlipTexture.y) {
|
||||
uv.y = 1.0 - uv.y;
|
||||
}
|
||||
frag.color = out_color * color * texture(tex, uv);
|
||||
}
|
||||
else {
|
||||
frag.color = out_color * color;
|
||||
}
|
||||
frag.depth = depth;
|
||||
return frag;
|
||||
}
|
||||
43
shaders/core/xyzuvrgba_vs.glsl
Normal file
43
shaders/core/xyzuvrgba_vs.glsl
Normal file
@@ -0,0 +1,43 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2021 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
|
||||
* software and associated documentation files (the "Software"), to deal in the Software *
|
||||
* without restriction, including without limitation the rights to use, copy, modify, *
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
|
||||
* permit persons to whom the Software is furnished to do so, subject to the following *
|
||||
* conditions: *
|
||||
* *
|
||||
* The above copyright notice and this permission notice shall be included in all copies *
|
||||
* or substantial portions of the Software. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#version __CONTEXT__
|
||||
|
||||
layout(location = 0) in vec3 in_position;
|
||||
layout(location = 1) in vec2 in_uv;
|
||||
layout(location = 2) in vec4 in_color;
|
||||
|
||||
out float depth;
|
||||
out vec2 out_uv;
|
||||
out vec4 out_color;
|
||||
|
||||
uniform mat4 proj;
|
||||
|
||||
void main() {
|
||||
out_uv = in_uv;
|
||||
out_color = in_color;
|
||||
vec4 p = proj * vec4(in_position, 1.0);
|
||||
gl_Position = p;
|
||||
depth = p.w;
|
||||
}
|
||||
@@ -416,8 +416,6 @@ void OpenSpaceEngine::initializeGL() {
|
||||
glbinding::Binding::initialize(global::windowDelegate->openGLProcedureAddress);
|
||||
//glbinding::Binding::useCurrentContext();
|
||||
|
||||
rendering::helper::initialize();
|
||||
|
||||
LDEBUG("Adding system components");
|
||||
// Detect and log OpenCL and OpenGL versions and available devices
|
||||
SysCap.addComponent(
|
||||
@@ -427,7 +425,6 @@ void OpenSpaceEngine::initializeGL() {
|
||||
std::make_unique<ghoul::systemcapabilities::OpenGLCapabilitiesComponent>()
|
||||
);
|
||||
|
||||
// @BUG: This will call OpenGL functions, should it should be in the initializeGL
|
||||
LDEBUG("Detecting capabilities");
|
||||
SysCap.detectCapabilities();
|
||||
|
||||
@@ -467,6 +464,8 @@ void OpenSpaceEngine::initializeGL() {
|
||||
}
|
||||
}
|
||||
|
||||
rendering::helper::initialize();
|
||||
|
||||
loadFonts();
|
||||
|
||||
_loadingScreen = std::make_unique<LoadingScreen>(
|
||||
|
||||
@@ -266,10 +266,14 @@ int removeTag(lua_State* L) {
|
||||
* Downloads a file from Lua interpreter
|
||||
*/
|
||||
int downloadFile(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::addTag");
|
||||
int n = ghoul::lua::checkArgumentsAndThrow(L, {2, 3}, "lua::addTag");
|
||||
|
||||
const std::string& uri = ghoul::lua::value<std::string>(L, 1);
|
||||
const std::string& savePath = ghoul::lua::value<std::string>(L, 2);
|
||||
bool waitForComplete = false;
|
||||
if (n == 3) {
|
||||
waitForComplete = ghoul::lua::value<bool>(L, 3);
|
||||
}
|
||||
lua_settop(L, 0);
|
||||
|
||||
LINFOC("OpenSpaceEngine", fmt::format("Downloading file from {}", uri));
|
||||
@@ -281,6 +285,14 @@ int downloadFile(lua_State* L) {
|
||||
DownloadManager::FailOnError::Yes,
|
||||
5
|
||||
);
|
||||
|
||||
if (waitForComplete) {
|
||||
while (!future->isFinished && future->errorMessage.empty() ) {
|
||||
//just wait
|
||||
LTRACEC("OpenSpaceEngine", fmt::format("waiting {}", future->errorMessage));
|
||||
}
|
||||
}
|
||||
|
||||
if (!future || !future->isFinished) {
|
||||
return ghoul::lua::luaError(
|
||||
L,
|
||||
|
||||
@@ -459,8 +459,8 @@ void OrbitalNavigator::updateCameraStateFromStates(double deltaTime) {
|
||||
if (_applyLinearFlight) {
|
||||
// Calculate a position handle based on the camera position in world space
|
||||
glm::dvec3 camPosToAnchorPosDiff = prevCameraPosition - anchorPos;
|
||||
// Use the boundingsphere to get an approximate distance to the node surface
|
||||
double nodeRadius = static_cast<double>(_anchorNode->boundingSphere());
|
||||
// Use the interaction sphere to get an approximate distance to the node surface
|
||||
double nodeRadius = static_cast<double>(_anchorNode->interactionSphere());
|
||||
double distFromCameraToFocus =
|
||||
glm::distance(prevCameraPosition, anchorPos) - nodeRadius;
|
||||
|
||||
|
||||
@@ -23,21 +23,17 @@
|
||||
****************************************************************************************/
|
||||
|
||||
#include <openspace/properties/property.h>
|
||||
|
||||
#include <openspace/properties/propertyowner.h>
|
||||
|
||||
#include <ghoul/lua/ghoul_lua.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/lua/ghoul_lua.h>
|
||||
#include <ghoul/misc/dictionaryjsonformatter.h>
|
||||
#include <algorithm>
|
||||
|
||||
namespace {
|
||||
constexpr const char* MetaDataKeyGroup = "Group";
|
||||
constexpr const char* MetaDataKeyVisibility = "Visibility";
|
||||
constexpr const char* MetaDataKeyReadOnly = "isReadOnly";
|
||||
|
||||
constexpr const char* _metaDataKeyViewPrefix = "view";
|
||||
constexpr const char* MetaDataKeyViewOptions = "ViewOptions";
|
||||
constexpr const char* MetaDataKeyVisibility = "Visibility";
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -46,8 +42,8 @@ namespace openspace::properties {
|
||||
Property::OnChangeHandle Property::OnChangeHandleAll =
|
||||
std::numeric_limits<OnChangeHandle>::max();
|
||||
|
||||
const char* Property::ViewOptions::Color = "color";
|
||||
const char* Property::ViewOptions::LightPosition = "lightPosition";
|
||||
const char* Property::ViewOptions::Color = "Color";
|
||||
const char* Property::ViewOptions::Logarithmic = "Logarithmic";
|
||||
|
||||
const char* Property::IdentifierKey = "Identifier";
|
||||
const char* Property::NameKey = "Name";
|
||||
@@ -209,14 +205,14 @@ void Property::setReadOnly(bool state) {
|
||||
void Property::setViewOption(std::string option, bool value) {
|
||||
ghoul::Dictionary d;
|
||||
d.setValue(option, value);
|
||||
_metaData.setValue(_metaDataKeyViewPrefix, d);
|
||||
_metaData.setValue(MetaDataKeyViewOptions, d);
|
||||
}
|
||||
|
||||
bool Property::viewOption(const std::string& option, bool defaultValue) const {
|
||||
if (!_metaData.hasValue<ghoul::Dictionary>(_metaDataKeyViewPrefix)) {
|
||||
if (!_metaData.hasValue<ghoul::Dictionary>(MetaDataKeyViewOptions)) {
|
||||
return defaultValue;
|
||||
}
|
||||
ghoul::Dictionary d = _metaData.value<ghoul::Dictionary>(_metaDataKeyViewPrefix);
|
||||
ghoul::Dictionary d = _metaData.value<ghoul::Dictionary>(MetaDataKeyViewOptions);
|
||||
if (d.hasKey(option)) {
|
||||
return d.value<bool>(option);
|
||||
}
|
||||
@@ -357,18 +353,23 @@ std::string Property::generateMetaDataJsonDescription() const {
|
||||
if (_metaData.hasValue<bool>(MetaDataKeyReadOnly)) {
|
||||
isReadOnly = _metaData.value<bool>(MetaDataKeyReadOnly);
|
||||
}
|
||||
std::string isReadOnlyString = (isReadOnly ? "true" : "false");
|
||||
|
||||
std::string gIdent = groupIdentifier();
|
||||
std::string gIdentSan = sanitizeString(gIdent);
|
||||
std::string groupId = groupIdentifier();
|
||||
std::string sanitizedGroupId = sanitizeString(groupId);
|
||||
|
||||
std::string viewOptions = "{}";
|
||||
if (_metaData.hasValue<ghoul::Dictionary>(MetaDataKeyViewOptions)) {
|
||||
viewOptions = ghoul::formatJson(
|
||||
_metaData.value<ghoul::Dictionary>(MetaDataKeyViewOptions)
|
||||
);
|
||||
}
|
||||
|
||||
std::string result = "{ ";
|
||||
result +=
|
||||
"\"" + std::string(MetaDataKeyGroup) + "\": \"" + gIdentSan + "\", ";
|
||||
result +=
|
||||
"\"" + std::string(MetaDataKeyVisibility) + "\": \"" + vis + "\", ";
|
||||
result +=
|
||||
"\"" + std::string(MetaDataKeyReadOnly) + "\": " +
|
||||
(isReadOnly ? "true" : "false");
|
||||
result += fmt::format("\"{}\": \"{}\",", MetaDataKeyGroup, sanitizedGroupId);
|
||||
result += fmt::format("\"{}\": \"{}\",", MetaDataKeyVisibility, vis);
|
||||
result += fmt::format("\"{}\": {},", MetaDataKeyReadOnly, isReadOnlyString);
|
||||
result += fmt::format("\"{}\": {}", MetaDataKeyViewOptions, viewOptions);
|
||||
result += " }";
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -53,17 +53,20 @@ layout(location = 0) in vec2 in_position;
|
||||
layout(location = 1) in vec2 in_uv;
|
||||
layout(location = 2) in vec4 in_color;
|
||||
|
||||
out float depth;
|
||||
out vec2 out_position;
|
||||
out vec2 out_uv;
|
||||
out vec4 out_color;
|
||||
|
||||
uniform mat4 ortho;
|
||||
uniform mat4 proj;
|
||||
|
||||
void main() {
|
||||
out_position = in_position;
|
||||
out_uv = in_uv;
|
||||
out_color = in_color;
|
||||
gl_Position = ortho * vec4(in_position, 0.0, 1.0);
|
||||
vec4 p = proj * vec4(in_position, 0.0, 1.0);
|
||||
gl_Position = p;
|
||||
depth = p.w;
|
||||
}
|
||||
|
||||
)";
|
||||
@@ -90,11 +93,14 @@ void main() {
|
||||
constexpr const char* XyuvrgbaFragmentCode = R"(
|
||||
#version __CONTEXT__
|
||||
|
||||
#include "fragment.glsl"
|
||||
|
||||
uniform bool hasTexture = false;
|
||||
uniform bvec2 shouldFlipTexture = bvec2(false, false);
|
||||
uniform sampler2D tex;
|
||||
uniform vec4 color = vec4(1.0, 1.0, 1.0, 1.0);
|
||||
|
||||
in float depth;
|
||||
in vec2 out_uv;
|
||||
in vec4 out_color;
|
||||
|
||||
@@ -119,6 +125,7 @@ void main() {
|
||||
|
||||
} // namespace
|
||||
|
||||
#pragma optimize ("", off)
|
||||
namespace openspace::rendering::helper {
|
||||
|
||||
namespace detail {
|
||||
@@ -150,7 +157,6 @@ void initialize() {
|
||||
vertexFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
|
||||
vertexFile.open(xyuvrgbaVertexFile, std::fstream::out);
|
||||
vertexFile << XyuvrgbaVertexCode;
|
||||
vertexFile.close();
|
||||
}
|
||||
|
||||
xyuvrgbaFragmentFile = absPath("${TEMPORARY}/xyuvrgba.frag");
|
||||
@@ -159,13 +165,17 @@ void initialize() {
|
||||
fragmentFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
|
||||
fragmentFile.open(xyuvrgbaFragmentFile, std::fstream::out);
|
||||
fragmentFile << XyuvrgbaFragmentCode;
|
||||
fragmentFile.close();
|
||||
}
|
||||
shaders.xyuvrgba.program = ghoul::opengl::ProgramObject::Build(
|
||||
"xyuvrgba", xyuvrgbaVertexFile, xyuvrgbaFragmentFile);
|
||||
ghoul::opengl::updateUniformLocations(*shaders.xyuvrgba.program,
|
||||
"xyuvrgba",
|
||||
xyuvrgbaVertexFile,
|
||||
xyuvrgbaFragmentFile
|
||||
);
|
||||
ghoul::opengl::updateUniformLocations(
|
||||
*shaders.xyuvrgba.program,
|
||||
shaders.xyuvrgba.cache,
|
||||
{ "tex", "hasTexture", "shouldFlipTexture", "ortho", "color" });
|
||||
{ "tex", "hasTexture", "shouldFlipTexture", "proj", "color" }
|
||||
);
|
||||
|
||||
//
|
||||
// Screenfilling shader
|
||||
@@ -176,7 +186,6 @@ void initialize() {
|
||||
vertexFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
|
||||
vertexFile.open(screenFillingVertexFile, std::fstream::out);
|
||||
vertexFile << ScreenFillingQuadVertexCode;
|
||||
vertexFile.close();
|
||||
}
|
||||
|
||||
screenFillingFragmentFile = absPath("${TEMPORARY}/screenfilling.frag");
|
||||
@@ -185,14 +194,18 @@ void initialize() {
|
||||
fragmentFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
|
||||
fragmentFile.open(screenFillingFragmentFile, std::fstream::out);
|
||||
fragmentFile << XyuvrgbaFragmentCode;
|
||||
fragmentFile.close();
|
||||
}
|
||||
|
||||
shaders.screenfilling.program = ghoul::opengl::ProgramObject::Build(
|
||||
"screenfilling", xyuvrgbaVertexFile, xyuvrgbaFragmentFile);
|
||||
ghoul::opengl::updateUniformLocations(*shaders.screenfilling.program,
|
||||
"screenfilling",
|
||||
xyuvrgbaVertexFile,
|
||||
xyuvrgbaFragmentFile
|
||||
);
|
||||
ghoul::opengl::updateUniformLocations(
|
||||
*shaders.screenfilling.program,
|
||||
shaders.screenfilling.cache,
|
||||
{ "tex", "hasTexture", "shouldFlipTexture", "ortho", "color" });
|
||||
{ "tex", "hasTexture", "shouldFlipTexture", "proj", "color" }
|
||||
);
|
||||
|
||||
|
||||
//
|
||||
@@ -231,6 +244,45 @@ void initialize() {
|
||||
reinterpret_cast<GLvoid*>(offsetof(VertexXYUVRGBA, rgba)));
|
||||
glBindVertexArray(0);
|
||||
|
||||
//
|
||||
// Sphere vertex array object
|
||||
//
|
||||
std::pair<std::vector<Vertex>, std::vector<GLushort>> sphereData = createSphere(
|
||||
64, glm::vec3(1.f, 1.f, 1.f), glm::vec4(1.f, 1.f, 1.f, 1.f)
|
||||
);
|
||||
|
||||
glGenVertexArrays(1, &vertexObjects.sphere.vao);
|
||||
glGenBuffers(1, &vertexObjects.sphere.vbo);
|
||||
glGenBuffers(1, &vertexObjects.sphere.ibo);
|
||||
|
||||
glBindVertexArray(vertexObjects.sphere.vao);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vertexObjects.sphere.vbo);
|
||||
glBufferData(
|
||||
GL_ARRAY_BUFFER,
|
||||
sphereData.first.size() * sizeof(Vertex),
|
||||
sphereData.first.data(),
|
||||
GL_STATIC_DRAW
|
||||
);
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vertexObjects.sphere.ibo);
|
||||
glBufferData(
|
||||
GL_ELEMENT_ARRAY_BUFFER,
|
||||
sphereData.second.size() * sizeof(GLushort),
|
||||
sphereData.second.data(),
|
||||
GL_STATIC_DRAW
|
||||
);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), nullptr);
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex),
|
||||
reinterpret_cast<GLvoid*>(offsetof(Vertex, uv)));
|
||||
glEnableVertexAttribArray(2);
|
||||
glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex),
|
||||
reinterpret_cast<GLvoid*>(offsetof(Vertex, rgba)));
|
||||
glBindVertexArray(0);
|
||||
vertexObjects.sphere.nElements = static_cast<int>(sphereData.second.size());
|
||||
|
||||
|
||||
//
|
||||
// Empty vertex array objects
|
||||
//
|
||||
@@ -262,6 +314,10 @@ void deinitialize() {
|
||||
glDeleteVertexArrays(1, &vertexObjects.square.vao);
|
||||
glDeleteBuffers(1, &vertexObjects.square.vbo);
|
||||
|
||||
glDeleteVertexArrays(1, &vertexObjects.sphere.vao);
|
||||
glDeleteBuffers(1, &vertexObjects.sphere.vbo);
|
||||
glDeleteBuffers(1, &vertexObjects.sphere.ibo);
|
||||
|
||||
glDeleteVertexArrays(1, &vertexObjects.empty.vao);
|
||||
|
||||
isInitialized = false;
|
||||
@@ -316,14 +372,14 @@ void renderBox(ghoul::opengl::ProgramObject& program, GLint orthoLocation,
|
||||
}
|
||||
|
||||
void renderBox(const glm::vec2& position, const glm::vec2& size, const glm::vec4& color,
|
||||
Anchor anchor)
|
||||
Anchor anchor)
|
||||
{
|
||||
auto& shdr = shaders.xyuvrgba;
|
||||
shdr.program->activate();
|
||||
shdr.program->setUniform(shdr.cache.hasTexture, 0);
|
||||
renderBox(
|
||||
*shdr.program,
|
||||
shdr.cache.ortho,
|
||||
shdr.cache.proj,
|
||||
shdr.cache.color,
|
||||
position, size,
|
||||
color,
|
||||
@@ -345,7 +401,7 @@ void renderBox(const glm::vec2& position, const glm::vec2& size, const glm::vec4
|
||||
shdr.program->setUniform(shdr.cache.tex, unit);
|
||||
renderBox(
|
||||
*shdr.program,
|
||||
shdr.cache.ortho,
|
||||
shdr.cache.proj,
|
||||
shdr.cache.color,
|
||||
position,
|
||||
size,
|
||||
@@ -388,4 +444,63 @@ std::vector<Vertex> createRing(int nSegments, float radius, glm::vec4 colors) {
|
||||
return vertices;
|
||||
}
|
||||
|
||||
std::pair<std::vector<Vertex>, std::vector<GLushort>> createSphere(int nSegments,
|
||||
glm::vec3 radii,
|
||||
glm::vec4 colors)
|
||||
{
|
||||
std::vector<Vertex> vertices;
|
||||
vertices.reserve(nSegments * nSegments);
|
||||
for (int i = 0; i <= nSegments; i++) {
|
||||
for (int j = 0; j <= nSegments; j++) {
|
||||
const float fi = static_cast<float>(i);
|
||||
const float fj = static_cast<float>(j);
|
||||
// inclination angle (north to south)
|
||||
// 0 -> PI
|
||||
// azimuth angle (east to west)
|
||||
const float theta = fi * glm::pi<float>() / nSegments;
|
||||
|
||||
// 0 -> 2*PI
|
||||
const float phi = fj * glm::pi<float>() * 2.f / nSegments;
|
||||
|
||||
const float x = radii[0] * sin(theta) * cos(phi);
|
||||
const float y = radii[1] * sin(theta) * sin(phi);
|
||||
const float z = radii[2] * cos(theta); // Z points towards pole (theta = 0)
|
||||
|
||||
Vertex v;
|
||||
v.xyz[0] = x;
|
||||
v.xyz[1] = y;
|
||||
v.xyz[2] = z;
|
||||
|
||||
const float t1 = fj / nSegments;
|
||||
const float t2 = 1.f - (fi / nSegments);
|
||||
|
||||
v.uv[0] = t1;
|
||||
v.uv[1] = t2;
|
||||
|
||||
v.rgba[0] = colors.r;
|
||||
v.rgba[1] = colors.g;
|
||||
v.rgba[2] = colors.b;
|
||||
v.rgba[3] = colors.a;
|
||||
|
||||
vertices.push_back(v);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<GLushort> indices;
|
||||
indices.reserve(vertices.size() * 3);
|
||||
for (int i = 1; i <= nSegments; i++) {
|
||||
for (int j = 0; j < nSegments; j++) {
|
||||
const int t = nSegments + 1;
|
||||
indices.push_back(static_cast<GLushort>(t * (i - 1) + j + 0));
|
||||
indices.push_back(static_cast<GLushort>(t * (i + 0) + j + 0));
|
||||
indices.push_back(static_cast<GLushort>(t * (i + 0) + j + 1));
|
||||
indices.push_back(static_cast<GLushort>(t * (i - 1) + j + 0));
|
||||
indices.push_back(static_cast<GLushort>(t * (i + 0) + j + 1));
|
||||
indices.push_back(static_cast<GLushort>(t * (i - 1) + j + 1));
|
||||
}
|
||||
}
|
||||
|
||||
return { vertices, indices };
|
||||
}
|
||||
|
||||
} // namespace openspace::rendering::helper
|
||||
|
||||
@@ -58,11 +58,6 @@ namespace {
|
||||
openspace::properties::Property::Visibility::Hidden
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo BoundingSphereInfo = {
|
||||
"BoundingSphere",
|
||||
"Bounding Sphere",
|
||||
"The size of the bounding sphere radius."
|
||||
};
|
||||
struct [[codegen::Dictionary(Renderable)]] Parameters {
|
||||
// [[codegen::verbatim(EnabledInfo.description)]]
|
||||
std::optional<bool> enabled;
|
||||
@@ -76,9 +71,6 @@ namespace {
|
||||
|
||||
// [[codegen::verbatim(RenderableTypeInfo.description)]]
|
||||
std::optional<std::string> type;
|
||||
|
||||
// [[codegen::verbatim(BoundingSphereInfo.description)]]
|
||||
std::optional<float> boundingSphere;
|
||||
};
|
||||
#include "renderable_codegen.cpp"
|
||||
} // namespace
|
||||
@@ -120,7 +112,6 @@ Renderable::Renderable(const ghoul::Dictionary& dictionary)
|
||||
: properties::PropertyOwner({ "Renderable" })
|
||||
, _enabled(EnabledInfo, true)
|
||||
, _opacity(OpacityInfo, 1.f, 0.f, 1.f)
|
||||
, _boundingSphere(BoundingSphereInfo, 0.f, 0.f, 3e10f)
|
||||
, _renderableType(RenderableTypeInfo, "Renderable")
|
||||
{
|
||||
ZoneScoped
|
||||
@@ -154,9 +145,6 @@ Renderable::Renderable(const ghoul::Dictionary& dictionary)
|
||||
// set type for UI
|
||||
_renderableType = p.type.value_or(_renderableType);
|
||||
addProperty(_renderableType);
|
||||
|
||||
_boundingSphere = p.boundingSphere.value_or(_boundingSphere);
|
||||
addProperty(_boundingSphere);
|
||||
}
|
||||
|
||||
void Renderable::initialize() {}
|
||||
@@ -179,12 +167,16 @@ double Renderable::boundingSphere() const {
|
||||
return _boundingSphere;
|
||||
}
|
||||
|
||||
double Renderable::interactionSphere() const {
|
||||
return _interactionSphere;
|
||||
}
|
||||
|
||||
SurfacePositionHandle Renderable::calculateSurfacePositionHandle(
|
||||
const glm::dvec3& targetModelSpace) const
|
||||
{
|
||||
const glm::dvec3 directionFromCenterToTarget = glm::normalize(targetModelSpace);
|
||||
return {
|
||||
directionFromCenterToTarget * boundingSphere(),
|
||||
directionFromCenterToTarget * _parent->interactionSphere(),
|
||||
directionFromCenterToTarget,
|
||||
0.0
|
||||
};
|
||||
|
||||
@@ -1116,30 +1116,18 @@ void RenderEngine::takeScreenshot() {
|
||||
_latestScreenshotNumber = global::windowDelegate->takeScreenshot(_applyWarping);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the latest screenshot filename
|
||||
*/
|
||||
unsigned int RenderEngine::latestScreenshotNumber() const {
|
||||
return _latestScreenshotNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set raycasting uniforms on the program object, and setup raycasting.
|
||||
*/
|
||||
void RenderEngine::preRaycast(ghoul::opengl::ProgramObject& programObject) {
|
||||
_renderer->preRaycast(programObject);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tear down raycasting for the specified program object.
|
||||
*/
|
||||
void RenderEngine::postRaycast(ghoul::opengl::ProgramObject& programObject) {
|
||||
_renderer->postRaycast(programObject);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set renderer
|
||||
*/
|
||||
void RenderEngine::setRenderer(std::unique_ptr<Renderer> renderer) {
|
||||
ZoneScoped
|
||||
|
||||
|
||||
@@ -31,12 +31,15 @@
|
||||
#include <openspace/documentation/verifier.h>
|
||||
#include <openspace/engine/globals.h>
|
||||
#include <openspace/engine/windowdelegate.h>
|
||||
#include <openspace/rendering/helper.h>
|
||||
#include <openspace/rendering/renderable.h>
|
||||
#include <openspace/rendering/renderengine.h>
|
||||
#include <openspace/scene/scene.h>
|
||||
#include <openspace/scene/timeframe.h>
|
||||
#include <openspace/util/memorymanager.h>
|
||||
#include <openspace/util/updatestructures.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <ghoul/misc/assert.h>
|
||||
#include <ghoul/misc/profiling.h>
|
||||
#include <ghoul/opengl/ghoul_gl.h>
|
||||
@@ -89,11 +92,23 @@ namespace {
|
||||
constexpr openspace::properties::Property::PropertyInfo BoundingSphereInfo = {
|
||||
"BoundingSphere",
|
||||
"Bounding Sphere",
|
||||
"The bounding sphere of the scene graph node. This can be the "
|
||||
"bounding sphere of an attached renderable or directly specified to the node. "
|
||||
"If there is a boundingsphere on both the renderable and the node, the largest "
|
||||
"number will be picked.",
|
||||
openspace::properties::Property::Visibility::Hidden
|
||||
"The bounding sphere of the scene graph node meaning that everything that this "
|
||||
"scene graph node renders must be contained within this sphere. This value is "
|
||||
"only used as an override to the bounding sphere calculated by the Renderable, "
|
||||
"if present. If this value is -1, the Renderable's computed bounding sphere is "
|
||||
"used",
|
||||
openspace::properties::Property::Visibility::Developer
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo InteractionSphereInfo = {
|
||||
"InteractionSphere",
|
||||
"Interaction Sphere",
|
||||
"The minimum radius that the camera is allowed to get close to this scene graph "
|
||||
"node. This value is "
|
||||
"only used as an override to the bounding sphere calculated by the Renderable, "
|
||||
"if present. If this value is -1, the Renderable's computed interaction sphere "
|
||||
"is used",
|
||||
openspace::properties::Property::Visibility::Developer
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo GuiPathInfo = {
|
||||
@@ -128,6 +143,14 @@ namespace {
|
||||
openspace::properties::Property::Visibility::Hidden
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo ShowDebugSphereInfo = {
|
||||
"ShowDebugSphere",
|
||||
"Show Debug Sphere",
|
||||
"If enabled the bounding sphere of this scene graph node is rendered as a debug "
|
||||
"method",
|
||||
openspace::properties::Property::Visibility::Developer
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(SceneGraphNode)]] Parameters {
|
||||
// The identifier of this scenegraph node. This name must be unique among all
|
||||
// scene graph nodes that are loaded in a specific scene. If a duplicate is
|
||||
@@ -156,6 +179,10 @@ namespace {
|
||||
// sphere needs to be overwritten for some reason
|
||||
std::optional<double> boundingSphere;
|
||||
|
||||
// A hard-coded radius for limiting the interaction radius, meaning the minimal
|
||||
// distance that the camera can approach this scene graph node
|
||||
std::optional<double> interactionSphere;
|
||||
|
||||
struct Transform {
|
||||
// This node describes a translation that is applied to the scenegraph node
|
||||
// and all its children. Depending on the 'Type' of the translation, this can
|
||||
@@ -258,10 +285,8 @@ ghoul::mm_unique_ptr<SceneGraphNode> SceneGraphNode::createFromDictionary(
|
||||
}
|
||||
}
|
||||
|
||||
if (p.boundingSphere.has_value()) {
|
||||
result->_boundingSphere = *p.boundingSphere;
|
||||
result->_boundingSphere.setVisibility(properties::Property::Visibility::All);
|
||||
}
|
||||
result->_overrideBoundingSphere = p.boundingSphere;
|
||||
result->_overrideInteractionSphere = p.interactionSphere;
|
||||
|
||||
if (p.transform.has_value()) {
|
||||
if (p.transform->translation.has_value()) {
|
||||
@@ -345,23 +370,11 @@ ghoul::mm_unique_ptr<SceneGraphNode> SceneGraphNode::createFromDictionary(
|
||||
if (p.renderable.has_value()) {
|
||||
result->_renderable = Renderable::createFromDictionary(*p.renderable);
|
||||
ghoul_assert(result->_renderable, "Failed to create Renderable");
|
||||
result->_renderable->_parent = result.get();
|
||||
result->addPropertySubOwner(result->_renderable.get());
|
||||
LDEBUG(fmt::format(
|
||||
"Successfully created renderable for '{}'", result->identifier()
|
||||
));
|
||||
|
||||
// If the renderable child has a larger bounding sphere, we allow it to override
|
||||
if (result->_renderable->boundingSphere() > result->_boundingSphere) {
|
||||
result->_boundingSphere = result->_renderable->boundingSphere();
|
||||
|
||||
if (p.boundingSphere.has_value()) {
|
||||
LWARNING(fmt::format(
|
||||
"The specified property 'BoundingSphere' for '{}' was overwritten "
|
||||
"by a child renderable",
|
||||
result->_identifier
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (p.tag.has_value()) {
|
||||
@@ -392,6 +405,8 @@ documentation::Documentation SceneGraphNode::Documentation() {
|
||||
return doc;
|
||||
}
|
||||
|
||||
ghoul::opengl::ProgramObject* SceneGraphNode::_debugSphereProgram = nullptr;
|
||||
|
||||
SceneGraphNode::SceneGraphNode()
|
||||
: properties::PropertyOwner({ "" })
|
||||
, _guiHidden(GuiHiddenInfo)
|
||||
@@ -409,13 +424,15 @@ SceneGraphNode::SceneGraphNode()
|
||||
global::memoryManager->PersistentMemory.alloc<StaticScale>()
|
||||
)
|
||||
}
|
||||
, _boundingSphere(BoundingSphereInfo, 0.0)
|
||||
, _boundingSphere(BoundingSphereInfo, -1.0, -1.0, 1e12)
|
||||
, _interactionSphere(InteractionSphereInfo, -1.0, -1.0, -1.0, 1e12)
|
||||
, _computeScreenSpaceValues(ComputeScreenSpaceInfo, false)
|
||||
, _screenSpacePosition(ScreenSpacePositionInfo, glm::ivec2(-1, -1))
|
||||
, _screenVisibility(ScreenVisibilityInfo, false)
|
||||
, _distFromCamToNode(DistanceFromCamToNodeInfo, -1.0)
|
||||
, _screenSizeRadius(ScreenSizeRadiusInfo, 0)
|
||||
, _visibilityDistance(VisibilityDistanceInfo, 6e10f)
|
||||
, _showDebugSphere(ShowDebugSphereInfo, false)
|
||||
{
|
||||
addProperty(_computeScreenSpaceValues);
|
||||
addProperty(_screenSpacePosition);
|
||||
@@ -423,7 +440,25 @@ SceneGraphNode::SceneGraphNode()
|
||||
addProperty(_distFromCamToNode);
|
||||
addProperty(_screenSizeRadius);
|
||||
addProperty(_visibilityDistance);
|
||||
_boundingSphere.onChange([this]() {
|
||||
if (_boundingSphere >= 0.0) {
|
||||
_overrideBoundingSphere = _boundingSphere;
|
||||
}
|
||||
else {
|
||||
_overrideBoundingSphere = std::nullopt;
|
||||
}
|
||||
});
|
||||
addProperty(_boundingSphere);
|
||||
_interactionSphere.onChange([this]() {
|
||||
if (_interactionSphere >= 0.0) {
|
||||
_overrideInteractionSphere = _interactionSphere;
|
||||
}
|
||||
else {
|
||||
_overrideInteractionSphere = std::nullopt;
|
||||
}
|
||||
});
|
||||
addProperty(_interactionSphere);
|
||||
addProperty(_showDebugSphere);
|
||||
}
|
||||
|
||||
SceneGraphNode::~SceneGraphNode() {} // NOLINT
|
||||
@@ -461,6 +496,25 @@ void SceneGraphNode::initializeGL() {
|
||||
if (_renderable) {
|
||||
_renderable->initializeGL();
|
||||
}
|
||||
|
||||
// The first one to get here will create program shared between all scene graph nodes
|
||||
if (_debugSphereProgram == nullptr) {
|
||||
std::unique_ptr<ghoul::opengl::ProgramObject> shader =
|
||||
global::renderEngine->buildRenderProgram(
|
||||
"DebugSphere",
|
||||
absPath("${SHADERS}/core/xyzuvrgba_vs.glsl"),
|
||||
absPath("${SHADERS}/core/xyzuvrgba_fs.glsl")
|
||||
);
|
||||
// Since we are only going to create a single of these shaders for the lifetime of
|
||||
// the program, we are not bothering with freeing it as the overhead of detecting
|
||||
// when the last scenegraph node will be destroyed would be a bit too much for the
|
||||
// benefit that we would gain from it
|
||||
_debugSphereProgram = shader.release();
|
||||
_debugSphereProgram->setIgnoreUniformLocationError(
|
||||
ghoul::opengl::ProgramObject::IgnoreError::Yes
|
||||
);
|
||||
}
|
||||
|
||||
_state = State::GLInitialized;
|
||||
|
||||
LDEBUG(fmt::format("Finished initializating GL: {}", identifier()));
|
||||
@@ -598,6 +652,59 @@ void SceneGraphNode::render(const RenderData& data, RendererTasks& tasks) {
|
||||
computeScreenSpaceData(newData);
|
||||
}
|
||||
}
|
||||
|
||||
if (_showDebugSphere) {
|
||||
if (const double bs = boundingSphere(); bs > 0.0) {
|
||||
renderDebugSphere(data.camera, bs, glm::vec4(0.5f, 0.15f, 0.5f, 0.75f));
|
||||
}
|
||||
|
||||
if (const double is = interactionSphere(); is > 0.0) {
|
||||
renderDebugSphere(data.camera, is, glm::vec4(0.15f, 0.35f, 0.85f, 0.75f));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SceneGraphNode::renderDebugSphere(const Camera& camera, double size, glm::vec4 color)
|
||||
{
|
||||
glm::dvec3 scaleVec = _worldScaleCached * size;
|
||||
glm::dmat4 modelTransform =
|
||||
glm::translate(glm::dmat4(1.0), _worldPositionCached) *
|
||||
glm::dmat4(_worldRotationCached) *
|
||||
glm::scale(glm::dmat4(1.0), scaleVec);
|
||||
|
||||
glm::mat4 modelViewProjection = camera.projectionMatrix() *
|
||||
glm::mat4(camera.combinedViewMatrix() * modelTransform);
|
||||
|
||||
_debugSphereProgram->activate();
|
||||
_debugSphereProgram->setUniform("hasTexture", 0);
|
||||
_debugSphereProgram->setUniform("proj", modelViewProjection);
|
||||
_debugSphereProgram->setUniform("color", color);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glDisable(GL_CULL_FACE);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
glBindVertexArray(rendering::helper::vertexObjects.sphere.vao);
|
||||
glDrawElements(
|
||||
GL_TRIANGLES,
|
||||
rendering::helper::vertexObjects.sphere.nElements,
|
||||
GL_UNSIGNED_SHORT,
|
||||
nullptr
|
||||
);
|
||||
|
||||
glLineWidth(2.0);
|
||||
_debugSphereProgram->setUniform("color", glm::vec4(1.f, 1.f, 1.f, 1.f));
|
||||
glDrawElements(
|
||||
GL_LINES,
|
||||
rendering::helper::vertexObjects.sphere.nElements,
|
||||
GL_UNSIGNED_SHORT,
|
||||
nullptr
|
||||
);
|
||||
|
||||
glBindVertexArray(0);
|
||||
|
||||
_debugSphereProgram->deactivate();
|
||||
}
|
||||
|
||||
void SceneGraphNode::setParent(SceneGraphNode& parent) {
|
||||
@@ -955,7 +1062,29 @@ std::vector<SceneGraphNode*> SceneGraphNode::children() const {
|
||||
}
|
||||
|
||||
double SceneGraphNode::boundingSphere() const {
|
||||
return _boundingSphere;
|
||||
if (_overrideBoundingSphere.has_value()) {
|
||||
return glm::compMax(scale() * *_overrideBoundingSphere);
|
||||
}
|
||||
|
||||
if (_renderable) {
|
||||
return glm::compMax(scale() * _renderable->boundingSphere());
|
||||
}
|
||||
else {
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
double SceneGraphNode::interactionSphere() const {
|
||||
if (_overrideInteractionSphere.has_value()) {
|
||||
return glm::compMax(scale() * *_overrideInteractionSphere);
|
||||
}
|
||||
|
||||
if (_renderable) {
|
||||
return glm::compMax(scale() * _renderable->interactionSphere());
|
||||
}
|
||||
else {
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
const Renderable* SceneGraphNode::renderable() const {
|
||||
|
||||
Reference in New Issue
Block a user