mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-01-05 11:09:37 -06:00
Include orientation data in new point cloud and remove RenderablePlanesCloud (#3168)
* WIP start including rotation data * Fix option to use orientation data or not * Renames to reflect that points are no longer billboarded (at least not always) * Increase max value for scale factor * Fix correct scaling for tully and deep sky objects * Remove the old RenderablePlanesCloud, we don't need it anymore * Add unit handling for size scaling from data values * Clarify some documentation about the points being rendered as planes * Update datasets to the new ones on the server * Use quaternions for orientation instead of vectors (simplifies interpolation and requires less data) * Make interpolation of orientation work * Fix size for deep sky objects being too small due to data being radius rather than diameter * Add IsRadius flag for deepsky * Update asset versions (major number update, due to breaking changes) --------- Co-authored-by: Alexander Bock <alexander.bock@liu.se>
This commit is contained in:
@@ -9,7 +9,7 @@ local speck = asset.resource({
|
||||
Name = "Deep Sky Objects Speck Files",
|
||||
Type = "HttpSynchronization",
|
||||
Identifier = "digitaluniverse_deepsky_speck",
|
||||
Version = 1
|
||||
Version = 2
|
||||
})
|
||||
|
||||
|
||||
@@ -57,19 +57,27 @@ local DeepSkyObjects = {
|
||||
local DeepSkyObjectsImages = {
|
||||
Identifier = "DeepSkyObjectsImages",
|
||||
Renderable = {
|
||||
Type = "RenderablePlanesCloud",
|
||||
Type = "RenderablePointCloud",
|
||||
Enabled = false,
|
||||
Color = { 1.0, 1.0, 1.0 },
|
||||
Opacity = 0.99,
|
||||
ScaleFactor = 1.0,
|
||||
File = speck .. "dso.speck",
|
||||
TexturePath = textures,
|
||||
Luminosity = "radius",
|
||||
ScaleLuminosity = 0.001,
|
||||
Texture = {
|
||||
Folder = textures
|
||||
},
|
||||
-- Use fixed orientation, and rotate planes based on orientation information in
|
||||
-- the dataset
|
||||
OrientationRenderOption = "Fixed Rotation",
|
||||
UseOrientationData = true,
|
||||
Unit = "pc",
|
||||
-- Fade in value in the same unit as "Unit"
|
||||
--FadeInDistances = {0.001, 0.05010},
|
||||
PlaneMinSize = 5.0
|
||||
SizeSettings = {
|
||||
SizeMapping = {
|
||||
ParameterOptions = { "radius" },
|
||||
ScaleFactor = "Parsec",
|
||||
IsRadius = true
|
||||
},
|
||||
-- No exponential scaling, just use size mapping to set the correct size
|
||||
ScaleExponent = 0.0
|
||||
}
|
||||
},
|
||||
Transform = {
|
||||
Rotation = {
|
||||
@@ -111,7 +119,7 @@ asset.export(DeepSkyObjectsImages)
|
||||
|
||||
asset.meta = {
|
||||
Name = "Deep Sky Objects Images",
|
||||
Version = "2.0",
|
||||
Version = "3.0",
|
||||
Description = "Digital Universe asset for Deep Sky Objects and their Images",
|
||||
Author = "Nate Greenstein, Matt Everhart, Brian Abbott (AMNH)",
|
||||
URL = "https://www.amnh.org/research/hayden-planetarium/digital-universe",
|
||||
|
||||
@@ -1,34 +1,41 @@
|
||||
local planeTextures = asset.resource({
|
||||
local textures = asset.resource({
|
||||
Name = "Milky Way Plane Textures",
|
||||
Type = "HttpSynchronization",
|
||||
Identifier = "digitaluniverse_milkyway_textures",
|
||||
Version = 2
|
||||
})
|
||||
|
||||
local planeSpeck = asset.resource({
|
||||
local speck = asset.resource({
|
||||
Name = "Milky Way Plane Speck",
|
||||
Type = "HttpSynchronization",
|
||||
Identifier = "digitaluniverse_milkyway_speck",
|
||||
Version = 1
|
||||
Version = 2
|
||||
})
|
||||
|
||||
|
||||
local Plane = {
|
||||
local Object = {
|
||||
Identifier = "MilkyWayGalaxyImage",
|
||||
Parent = "Root",
|
||||
Renderable = {
|
||||
Type = "RenderablePlanesCloud",
|
||||
Enabled = true,
|
||||
Color = { 1.0, 1.0, 1.0 },
|
||||
Type = "RenderablePointCloud",
|
||||
Opacity = 0.99,
|
||||
ScaleFactor = 2.8,
|
||||
File = planeSpeck .. "galaxy.speck",
|
||||
TexturePath = planeTextures,
|
||||
Luminosity = "size",
|
||||
ScaleLuminosity = 1.0,
|
||||
FadeInDistances = { 3000.0, 50000.0 },
|
||||
PlaneMinSize = 5.0,
|
||||
Unit = "pc"
|
||||
File = speck .. "galaxy.speck",
|
||||
Texture = {
|
||||
Folder = textures
|
||||
},
|
||||
-- Use fixed orientation, and rotate planes based on orientation information in
|
||||
-- the dataset
|
||||
OrientationRenderOption = "Fixed Rotation",
|
||||
UseOrientationData = true,
|
||||
Unit = "pc",
|
||||
Fading = {
|
||||
FadeInDistances = { 16000.0, 100000.0 } -- Fade in value in the same unit as "Unit"
|
||||
},
|
||||
SizeSettings = {
|
||||
SizeMapping = {
|
||||
ParameterOptions = { "size" }
|
||||
},
|
||||
ScaleExponent = 16.936
|
||||
},
|
||||
},
|
||||
GUI = {
|
||||
Name = "Milky Way Galaxy Image",
|
||||
@@ -46,20 +53,20 @@ local Plane = {
|
||||
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.addSceneGraphNode(Plane)
|
||||
openspace.addSceneGraphNode(Object)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.removeSceneGraphNode(Plane)
|
||||
openspace.removeSceneGraphNode(Object)
|
||||
end)
|
||||
|
||||
asset.export(Plane)
|
||||
asset.export(Object)
|
||||
|
||||
|
||||
|
||||
asset.meta = {
|
||||
Name = "MilkyWay Galaxy",
|
||||
Version = "2.1",
|
||||
Version = "3.0",
|
||||
Description = [[Digital Universe asset containt 2D image of the MilkyWay. For
|
||||
extragalactic viewing]],
|
||||
Author = "Brian Abbott, Carter Emmart (AMNH)",
|
||||
|
||||
@@ -1,34 +1,42 @@
|
||||
local planeTextures = asset.resource({
|
||||
local textures = asset.resource({
|
||||
Name = "Milky Way Plane Textures",
|
||||
Type = "HttpSynchronization",
|
||||
Identifier = "digitaluniverse_milkyway_textures",
|
||||
Version = 2
|
||||
})
|
||||
|
||||
local planeSpeck = asset.resource({
|
||||
local speck = asset.resource({
|
||||
Name = "Milky Way Plane Speck",
|
||||
Type = "HttpSynchronization",
|
||||
Identifier = "digitaluniverse_milkyway_speck",
|
||||
Version = 1
|
||||
Version = 2
|
||||
})
|
||||
|
||||
|
||||
local Object = {
|
||||
Identifier = "MilkyWayGalaxyArmLabelsImage",
|
||||
Parent = "Root",
|
||||
Renderable = {
|
||||
Type = "RenderablePlanesCloud",
|
||||
Type = "RenderablePointCloud",
|
||||
Enabled = false,
|
||||
Color = { 1.0, 1.0, 1.0 },
|
||||
Opacity = 0.99,
|
||||
ScaleFactor = 2.8,
|
||||
File = planeSpeck .. "galaxyArmLabels.speck",
|
||||
TexturePath = planeTextures,
|
||||
Luminosity = "size",
|
||||
ScaleLuminosity = 1.0,
|
||||
FadeInDistances = { 3000.0, 50000.0 },
|
||||
PlaneMinSize = 5.0,
|
||||
Unit = "pc"
|
||||
File = speck .. "galaxyArmLabels.speck",
|
||||
Texture = {
|
||||
Folder = textures
|
||||
},
|
||||
-- Use fixed orientation, and rotate planes based on orientation information in
|
||||
-- the dataset
|
||||
OrientationRenderOption = "Fixed Rotation",
|
||||
UseOrientationData = true,
|
||||
Unit = "pc",
|
||||
Fading = {
|
||||
FadeInDistances = { 8000.0, 140000.0 } -- Fade in value in the same unit as "Unit"
|
||||
},
|
||||
SizeSettings = {
|
||||
SizeMapping = {
|
||||
ParameterOptions = { "size" }
|
||||
},
|
||||
ScaleExponent = 16.936
|
||||
},
|
||||
},
|
||||
GUI = {
|
||||
Name = "Milky Way Arms Labels",
|
||||
@@ -56,7 +64,7 @@ asset.export(Object)
|
||||
|
||||
asset.meta = {
|
||||
Name = "Milky Way Arms Labels",
|
||||
Version = "1.1",
|
||||
Version = "2.0",
|
||||
Description = "Image with arm labels for the Milky Way galaxy",
|
||||
Author = "Brian Abbott (AMNH)",
|
||||
URL = "https://www.amnh.org/research/hayden-planetarium/digital-universe",
|
||||
|
||||
@@ -9,7 +9,7 @@ local speck = asset.resource({
|
||||
Name = "Tully Speck Files",
|
||||
Type = "HttpSynchronization",
|
||||
Identifier = "digitaluniverse_tully_speck",
|
||||
Version = 3
|
||||
Version = 4
|
||||
})
|
||||
|
||||
|
||||
@@ -84,20 +84,30 @@ local TullyGalaxies = {
|
||||
local TullyGalaxiesImages = {
|
||||
Identifier = "TullyGalaxiesImages",
|
||||
Renderable = {
|
||||
Type = "RenderablePlanesCloud",
|
||||
Enabled = true,
|
||||
Color = { 1.0, 1.0, 1.0 },
|
||||
Type = "RenderablePointCloud",
|
||||
Opacity = 0.99,
|
||||
ScaleFactor = 1.0,
|
||||
File = speck .. "tully.speck",
|
||||
TexturePath = textures,
|
||||
Luminosity = "diamkpc",
|
||||
ScaleLuminosity = 0.001,
|
||||
SkipFirstDataPoint = true,
|
||||
Texture = {
|
||||
Folder = textures
|
||||
},
|
||||
TransformationMatrix = TransformMatrix,
|
||||
-- Use fixed orientation, and rotate planes based on orientation information in
|
||||
-- the dataset
|
||||
OrientationRenderOption = "Fixed Rotation",
|
||||
UseOrientationData = true,
|
||||
Unit = "Mpc",
|
||||
-- Fade in value in the same unit as "Unit"
|
||||
FadeInDistances = {0.0005, 0.003},
|
||||
PlaneMinSize = 1.0
|
||||
Fading = {
|
||||
FadeInDistances = { 0.0005, 0.003 } -- Fade in value in the same unit as "Unit"
|
||||
},
|
||||
SizeSettings = {
|
||||
SizeMapping = {
|
||||
ParameterOptions = { "diamkpc" },
|
||||
ScaleFactor = "Kiloparsec"
|
||||
},
|
||||
-- No exponential scaling, just use size mapping to set the correct size
|
||||
ScaleExponent = 0.0
|
||||
}
|
||||
},
|
||||
GUI = {
|
||||
Name = "Tully Galaxies Images",
|
||||
@@ -133,7 +143,7 @@ asset.export(TullyGalaxiesImages)
|
||||
|
||||
asset.meta = {
|
||||
Name = "Tully Galaxies",
|
||||
Version = "4.0",
|
||||
Version = "5.0",
|
||||
Description = [[Digital Universe asset for Tully Galaxies, including point cloud and
|
||||
images]],
|
||||
Author = "Stuart Levy (NCSA/UIUC), Brian Abbott (AMNH)",
|
||||
|
||||
@@ -168,10 +168,10 @@ set(SHADER_FILES
|
||||
shaders/model_vs.glsl
|
||||
shaders/plane_fs.glsl
|
||||
shaders/plane_vs.glsl
|
||||
shaders/pointcloud/billboardpoint_fs.glsl
|
||||
shaders/pointcloud/billboardpoint_gs.glsl
|
||||
shaders/pointcloud/billboardpoint_vs.glsl
|
||||
shaders/pointcloud/billboardpoint_interpolated_vs.glsl
|
||||
shaders/pointcloud/pointcloud_fs.glsl
|
||||
shaders/pointcloud/pointcloud_gs.glsl
|
||||
shaders/pointcloud/pointcloud_vs.glsl
|
||||
shaders/pointcloud/pointcloud_interpolated_vs.glsl
|
||||
shaders/polygon_fs.glsl
|
||||
shaders/polygon_gs.glsl
|
||||
shaders/polygon_vs.glsl
|
||||
|
||||
@@ -321,12 +321,12 @@ void RenderableInterpolatedPoints::initializeShadersAndGlExtras() {
|
||||
_program = BaseModule::ProgramObjectManager.request(
|
||||
"RenderablePointCloud_Interpolated",
|
||||
[]() {
|
||||
std::filesystem::path path = absPath("${MODULE_BASE}/shaders/pointcloud/");
|
||||
std::filesystem::path path = absPath("${MODULE_BASE}/shaders/pointcloud");
|
||||
return global::renderEngine->buildRenderProgram(
|
||||
"RenderablePointCloud_Interpolated",
|
||||
path / "billboardpoint_interpolated_vs.glsl",
|
||||
path / "billboardpoint_fs.glsl",
|
||||
path / "billboardpoint_gs.glsl"
|
||||
path / "pointcloud_interpolated_vs.glsl",
|
||||
path / "pointcloud_fs.glsl",
|
||||
path / "pointcloud_gs.glsl"
|
||||
);
|
||||
}
|
||||
);
|
||||
@@ -368,9 +368,13 @@ int RenderableInterpolatedPoints::nAttributesPerPoint() const {
|
||||
// Use two more positions (xyz)
|
||||
n += 2 * 3;
|
||||
}
|
||||
if (useOrientationData()) {
|
||||
// Use one more orientation quaternion (wxyz)
|
||||
n += 4;
|
||||
}
|
||||
// And potentially some more color and size data
|
||||
n += _hasColorMapFile ? 1 : 0;
|
||||
n += _hasDatavarSize ? 1 : 0;
|
||||
n += hasColorData() ? 1 : 0;
|
||||
n += hasSizeData() ? 1 : 0;
|
||||
|
||||
return n;
|
||||
}
|
||||
@@ -430,29 +434,54 @@ void RenderableInterpolatedPoints::addPositionDataForPoint(unsigned int index,
|
||||
}
|
||||
|
||||
void RenderableInterpolatedPoints::addColorAndSizeDataForPoint(unsigned int index,
|
||||
std::vector<float>& result) const
|
||||
std::vector<float>& result) const
|
||||
{
|
||||
using namespace dataloader;
|
||||
auto [firstIndex, secondIndex] = interpolationIndices(index);
|
||||
const Dataset::Entry& e0 = _dataset.entries[firstIndex];
|
||||
const Dataset::Entry& e1 = _dataset.entries[secondIndex];
|
||||
|
||||
int colorParamIndex = currentColorParameterIndex();
|
||||
if (_hasColorMapFile && colorParamIndex >= 0) {
|
||||
if (hasColorData()) {
|
||||
const int colorParamIndex = currentColorParameterIndex();
|
||||
result.push_back(e0.data[colorParamIndex]);
|
||||
result.push_back(e1.data[colorParamIndex]);
|
||||
}
|
||||
|
||||
int sizeParamIndex = currentSizeParameterIndex();
|
||||
if (_hasDatavarSize && sizeParamIndex >= 0) {
|
||||
if (hasSizeData()) {
|
||||
const int sizeParamIndex = currentSizeParameterIndex();
|
||||
// @TODO: Consider more detailed control over the scaling. Currently the value
|
||||
// is multiplied with the value as is. Should have similar mapping properties
|
||||
// as the color mapping
|
||||
result.push_back(e0.data[sizeParamIndex]);
|
||||
result.push_back(e1.data[sizeParamIndex]);
|
||||
|
||||
// Convert to diameter if data is given as radius
|
||||
float multiplier = _sizeSettings.sizeMapping->isRadius ? 2.f : 1.f;
|
||||
result.push_back(multiplier * e0.data[sizeParamIndex]);
|
||||
result.push_back(multiplier * e1.data[sizeParamIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderableInterpolatedPoints::addOrientationDataForPoint(unsigned int index,
|
||||
std::vector<float>& result) const
|
||||
{
|
||||
using namespace dataloader;
|
||||
auto [firstIndex, secondIndex] = interpolationIndices(index);
|
||||
const Dataset::Entry& e0 = _dataset.entries[firstIndex];
|
||||
const Dataset::Entry& e1 = _dataset.entries[secondIndex];
|
||||
|
||||
glm::quat q0 = orientationQuaternion(e0);
|
||||
glm::quat q1 = orientationQuaternion(e1);
|
||||
|
||||
result.push_back(q0.x);
|
||||
result.push_back(q0.y);
|
||||
result.push_back(q0.z);
|
||||
result.push_back(q0.w);
|
||||
|
||||
result.push_back(q1.x);
|
||||
result.push_back(q1.y);
|
||||
result.push_back(q1.z);
|
||||
result.push_back(q1.w);
|
||||
}
|
||||
|
||||
void RenderableInterpolatedPoints::initializeBufferData() {
|
||||
if (_vao == 0) {
|
||||
glGenVertexArrays(1, &_vao);
|
||||
@@ -481,16 +510,21 @@ void RenderableInterpolatedPoints::initializeBufferData() {
|
||||
offset = bufferVertexAttribute("in_position_after", 3, attibutesPerPoint, offset);
|
||||
}
|
||||
|
||||
if (_hasColorMapFile) {
|
||||
if (hasColorData()) {
|
||||
offset = bufferVertexAttribute("in_colorParameter0", 1, attibutesPerPoint, offset);
|
||||
offset = bufferVertexAttribute("in_colorParameter1", 1, attibutesPerPoint, offset);
|
||||
}
|
||||
|
||||
if (_hasDatavarSize) {
|
||||
if (hasSizeData()) {
|
||||
offset = bufferVertexAttribute("in_scalingParameter0", 1, attibutesPerPoint, offset);
|
||||
offset = bufferVertexAttribute("in_scalingParameter1", 1, attibutesPerPoint, offset);
|
||||
}
|
||||
|
||||
if (useOrientationData()) {
|
||||
offset = bufferVertexAttribute("in_orientation0", 4, attibutesPerPoint, offset);
|
||||
offset = bufferVertexAttribute("in_orientation1", 4, attibutesPerPoint, offset);
|
||||
}
|
||||
|
||||
if (_hasSpriteTexture) {
|
||||
offset = bufferVertexAttribute("in_textureLayer", 1, attibutesPerPoint, offset);
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ protected:
|
||||
/**
|
||||
* Create the rendering data for the positions for the point with the given index
|
||||
* and append that to the result. Compared to the base class, this class may require
|
||||
* 2-4 positions, depending on if * spline interpolation is used or not.
|
||||
* 2-4 positions, depending on if spline interpolation is used or not.
|
||||
*
|
||||
* The values are computed based on the current interpolation value.
|
||||
*
|
||||
@@ -82,6 +82,9 @@ protected:
|
||||
void addColorAndSizeDataForPoint(unsigned int index,
|
||||
std::vector<float>& result) const override;
|
||||
|
||||
void addOrientationDataForPoint(unsigned int index,
|
||||
std::vector<float>& result) const override;
|
||||
|
||||
void initializeBufferData();
|
||||
void updateBufferData() override;
|
||||
|
||||
|
||||
@@ -44,6 +44,8 @@
|
||||
#include <ghoul/opengl/textureconversion.h>
|
||||
#include <ghoul/opengl/textureunit.h>
|
||||
#include <glm/gtx/string_cast.hpp>
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
#include <glm/gtx/vector_angle.hpp>
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
@@ -56,7 +58,7 @@
|
||||
namespace {
|
||||
constexpr std::string_view _loggerCat = "RenderablePointCloud";
|
||||
|
||||
constexpr std::array<const char*, 34> UniformNames = {
|
||||
constexpr std::array<const char*, 35> UniformNames = {
|
||||
"cameraViewMatrix", "projectionMatrix", "modelMatrix", "cameraPosition",
|
||||
"cameraLookUp", "renderOption", "maxAngularSize", "color", "opacity",
|
||||
"scaleExponent", "scaleFactor", "up", "right", "fadeInValue", "hasSpriteTexture",
|
||||
@@ -64,12 +66,13 @@ namespace {
|
||||
"nanColor", "useNanColor", "hideOutsideRange", "enableMaxSizeControl",
|
||||
"aboveRangeColor", "useAboveRangeColor", "belowRangeColor", "useBelowRangeColor",
|
||||
"hasDvarScaling", "dvarScaleFactor", "enableOutline", "outlineColor",
|
||||
"outlineWeight", "aspectRatioScale"
|
||||
"outlineWeight", "aspectRatioScale", "useOrientationData"
|
||||
};
|
||||
|
||||
enum RenderOption {
|
||||
ViewDirection = 0,
|
||||
PositionNormal
|
||||
PositionNormal,
|
||||
FixedRotation
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo TextureEnabledInfo = {
|
||||
@@ -146,15 +149,7 @@ namespace {
|
||||
"The labels for the points. If no label file is provided, the labels will be "
|
||||
"created to match the points in the data file. For a CSV file, you should then "
|
||||
"specify which column is the 'Name' column in the data mapping. For SPECK files "
|
||||
"the labels are created from the comment at the end of each line"
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo RenderOptionInfo = {
|
||||
"RenderOption",
|
||||
"Render Option",
|
||||
"Option wether the point billboards should face the camera or not. Used for "
|
||||
"non-linear display environments such as fisheye.",
|
||||
openspace::properties::Property::Visibility::AdvancedUser
|
||||
"the labels are created from the comment at the end of each line."
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo FadeInDistancesInfo = {
|
||||
@@ -199,6 +194,29 @@ namespace {
|
||||
openspace::properties::Property::Visibility::AdvancedUser
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo UseOrientationDataInfo = {
|
||||
"UseOrientationData",
|
||||
"Use Orientation Data",
|
||||
"Include the orietation data in the dataset when rendering the points, if there "
|
||||
"is any. To see the rotation, you also need to set the \"Orientation Render "
|
||||
"Option\" to \"Fixed Rotation\".",
|
||||
openspace::properties::Property::Visibility::AdvancedUser
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo OrientationRenderOptionInfo = {
|
||||
"OrientationRenderOption",
|
||||
"Orientation Render Option",
|
||||
"Controls how the planes for the points will be oriented. \"Camera View "
|
||||
"Direction\" rotates the points so that the plane is orthogonal to the viewing "
|
||||
"direction of the camera (useful for planar displays), and \"Camera Position "
|
||||
"Normal\" rotates the points towards the position of the camera (useful for "
|
||||
"spherical displays, like dome theaters). In both these cases the points will "
|
||||
"be billboarded towards the camera. In contrast, \"Fixed Rotation\" does not "
|
||||
"rotate the points at all based on the camera and should be used when the "
|
||||
"dataset contains orientation information for the points.",
|
||||
openspace::properties::Property::Visibility::AdvancedUser
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo NumShownDataPointsInfo = {
|
||||
"NumberOfDataPoints",
|
||||
"Number of Shown Data Points",
|
||||
@@ -207,6 +225,13 @@ namespace {
|
||||
openspace::properties::Property::Visibility::User
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo HasOrientationDataInfo = {
|
||||
"HasOrientationData",
|
||||
"Has Orientation Data",
|
||||
"Set to true if orientation data was read from the dataset",
|
||||
openspace::properties::Property::Visibility::AdvancedUser
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo ScaleExponentInfo = {
|
||||
"ScaleExponent",
|
||||
"Scale Exponent",
|
||||
@@ -215,7 +240,8 @@ namespace {
|
||||
"value should be. If not included, it is computed based on the maximum "
|
||||
"positional component of the data points. This is useful for showing the "
|
||||
"dataset at all, but you will likely want to change it to something that looks "
|
||||
"good.",
|
||||
"good. Note that a scale exponent of 0 leads to the points having a diameter of "
|
||||
"1 meter, i.e. no exponential scaling.",
|
||||
openspace::properties::Property::Visibility::User
|
||||
};
|
||||
|
||||
@@ -298,7 +324,7 @@ namespace {
|
||||
// fading, sprite texture, color mapping and whether the colors of overlapping points
|
||||
// should be blended additively or not.
|
||||
//
|
||||
// The point size depends on a few different things:
|
||||
// The points are rendered as planes whose size depends on a few different things:
|
||||
//
|
||||
// - At the core, scaling is done based on an exponential value, the 'ScaleExponent'.
|
||||
// A relatively small change to this value will lead to a large change in size.
|
||||
@@ -312,6 +338,9 @@ namespace {
|
||||
// - There is also an option to limit the size of the points based on a given max
|
||||
// size value.
|
||||
//
|
||||
// - And an option to scale the points based on a data value (see 'SizeMapping' in
|
||||
// 'SizeSettings')
|
||||
//
|
||||
// - To easily change the visual size of the points, the multiplicative 'ScaleFactor'
|
||||
// may be used. A value of 2 makes the points twice as large, visually, compared
|
||||
// to 1.
|
||||
@@ -364,10 +393,14 @@ namespace {
|
||||
|
||||
enum class [[codegen::map(RenderOption)]] RenderOption {
|
||||
ViewDirection [[codegen::key("Camera View Direction")]],
|
||||
PositionNormal [[codegen::key("Camera Position Normal")]]
|
||||
PositionNormal [[codegen::key("Camera Position Normal")]],
|
||||
FixedRotation [[codegen::key("Fixed Rotation")]]
|
||||
};
|
||||
// [[codegen::verbatim(RenderOptionInfo.description)]]
|
||||
std::optional<RenderOption> renderOption;
|
||||
// [[codegen::verbatim(OrientationRenderOptionInfo.description)]]
|
||||
std::optional<RenderOption> orientationRenderOption;
|
||||
|
||||
// [[codegen::verbatim(UseOrientationDataInfo.description)]]
|
||||
std::optional<bool> useOrientationData;
|
||||
|
||||
// [[codegen::verbatim(UseAdditiveBlendingInfo.description)]]
|
||||
std::optional<bool> useAdditiveBlending;
|
||||
@@ -465,7 +498,7 @@ documentation::Documentation RenderablePointCloud::Documentation() {
|
||||
RenderablePointCloud::SizeSettings::SizeSettings(const ghoul::Dictionary& dictionary)
|
||||
: properties::PropertyOwner({ "Sizing", "Sizing", ""})
|
||||
, scaleExponent(ScaleExponentInfo, 1.f, 0.f, 25.f)
|
||||
, scaleFactor(ScaleFactorInfo, 1.f, 0.f, 50.f)
|
||||
, scaleFactor(ScaleFactorInfo, 1.f, 0.f, 100.f)
|
||||
, useMaxSizeControl(UseMaxSizeControlInfo, false)
|
||||
, maxAngularSize(MaxSizeInfo, 1.f, 0.f, 45.f)
|
||||
{
|
||||
@@ -586,8 +619,13 @@ RenderablePointCloud::RenderablePointCloud(const ghoul::Dictionary& dictionary)
|
||||
, _fading(dictionary)
|
||||
, _useAdditiveBlending(UseAdditiveBlendingInfo, true)
|
||||
, _drawElements(DrawElementsInfo, true)
|
||||
, _renderOption(RenderOptionInfo, properties::OptionProperty::DisplayType::Dropdown)
|
||||
, _useRotation(UseOrientationDataInfo, false)
|
||||
, _renderOption(
|
||||
OrientationRenderOptionInfo,
|
||||
properties::OptionProperty::DisplayType::Dropdown
|
||||
)
|
||||
, _nDataPoints(NumShownDataPointsInfo, 0)
|
||||
, _hasOrientationData(HasOrientationDataInfo, false)
|
||||
{
|
||||
ZoneScoped;
|
||||
|
||||
@@ -609,15 +647,20 @@ RenderablePointCloud::RenderablePointCloud(const ghoul::Dictionary& dictionary)
|
||||
|
||||
_renderOption.addOption(RenderOption::ViewDirection, "Camera View Direction");
|
||||
_renderOption.addOption(RenderOption::PositionNormal, "Camera Position Normal");
|
||||
_renderOption.addOption(RenderOption::FixedRotation, "Fixed Rotation");
|
||||
|
||||
if (p.renderOption.has_value()) {
|
||||
_renderOption = codegen::map<RenderOption>(*p.renderOption);
|
||||
if (p.orientationRenderOption.has_value()) {
|
||||
_renderOption = codegen::map<RenderOption>(*p.orientationRenderOption);
|
||||
}
|
||||
else {
|
||||
_renderOption = RenderOption::ViewDirection;
|
||||
}
|
||||
addProperty(_renderOption);
|
||||
|
||||
_useRotation = p.useOrientationData.value_or(_useRotation);
|
||||
_useRotation.onChange([this]() { _dataIsDirty = true; });
|
||||
addProperty(_useRotation);
|
||||
|
||||
_useAdditiveBlending = p.useAdditiveBlending.value_or(_useAdditiveBlending);
|
||||
addProperty(_useAdditiveBlending);
|
||||
|
||||
@@ -669,10 +712,11 @@ RenderablePointCloud::RenderablePointCloud(const ghoul::Dictionary& dictionary)
|
||||
|
||||
_transformationMatrix = p.transformationMatrix.value_or(_transformationMatrix);
|
||||
|
||||
if (p.sizeSettings.has_value() && p.sizeSettings->sizeMapping.has_value()) {
|
||||
if (_sizeSettings.sizeMapping != nullptr) {
|
||||
_sizeSettings.sizeMapping->parameterOption.onChange(
|
||||
[this]() { _dataIsDirty = true; }
|
||||
);
|
||||
_sizeSettings.sizeMapping->isRadius.onChange([this]() { _dataIsDirty = true; });
|
||||
_hasDatavarSize = true;
|
||||
}
|
||||
|
||||
@@ -728,6 +772,9 @@ RenderablePointCloud::RenderablePointCloud(const ghoul::Dictionary& dictionary)
|
||||
|
||||
_nDataPoints.setReadOnly(true);
|
||||
addProperty(_nDataPoints);
|
||||
|
||||
_hasOrientationData.setReadOnly(true);
|
||||
addProperty(_hasOrientationData);
|
||||
}
|
||||
|
||||
bool RenderablePointCloud::isReady() const {
|
||||
@@ -768,6 +815,7 @@ void RenderablePointCloud::initialize() {
|
||||
}
|
||||
|
||||
_nDataPoints = static_cast<unsigned int>(_dataset.entries.size());
|
||||
_hasOrientationData = _dataset.orientationDataIndex >= 0;
|
||||
|
||||
// If no scale exponent was specified, compute one that will at least show the
|
||||
// points based on the scale of the positions in the dataset
|
||||
@@ -835,9 +883,9 @@ void RenderablePointCloud::initializeShadersAndGlExtras() {
|
||||
[]() {
|
||||
return global::renderEngine->buildRenderProgram(
|
||||
"RenderablePointCloud",
|
||||
absPath("${MODULE_BASE}/shaders/pointcloud/billboardpoint_vs.glsl"),
|
||||
absPath("${MODULE_BASE}/shaders/pointcloud/billboardpoint_fs.glsl"),
|
||||
absPath("${MODULE_BASE}/shaders/pointcloud/billboardpoint_gs.glsl")
|
||||
absPath("${MODULE_BASE}/shaders/pointcloud/pointcloud_vs.glsl"),
|
||||
absPath("${MODULE_BASE}/shaders/pointcloud/pointcloud_fs.glsl"),
|
||||
absPath("${MODULE_BASE}/shaders/pointcloud/pointcloud_gs.glsl")
|
||||
);
|
||||
}
|
||||
);
|
||||
@@ -1090,11 +1138,11 @@ float RenderablePointCloud::computeDistanceFadeValue(const RenderData& data) con
|
||||
|
||||
void RenderablePointCloud::setExtraUniforms() {}
|
||||
|
||||
void RenderablePointCloud::renderBillboards(const RenderData& data,
|
||||
const glm::dmat4& modelMatrix,
|
||||
const glm::dvec3& orthoRight,
|
||||
const glm::dvec3& orthoUp,
|
||||
float fadeInVariable)
|
||||
void RenderablePointCloud::renderPoints(const RenderData& data,
|
||||
const glm::dmat4& modelMatrix,
|
||||
const glm::dvec3& orthoRight,
|
||||
const glm::dvec3& orthoUp,
|
||||
float fadeInVariable)
|
||||
{
|
||||
if (!_hasDataFile || _dataset.entries.empty()) {
|
||||
return;
|
||||
@@ -1164,7 +1212,7 @@ void RenderablePointCloud::renderBillboards(const RenderData& data,
|
||||
_program->setUniform(_uniformCache.outlineColor, _colorSettings.outlineColor);
|
||||
_program->setUniform(_uniformCache.outlineWeight, _colorSettings.outlineWeight);
|
||||
|
||||
bool useColorMap = _hasColorMapFile && _colorSettings.colorMapping->enabled &&
|
||||
bool useColorMap = hasColorData() && _colorSettings.colorMapping->enabled &&
|
||||
_colorSettings.colorMapping->texture();
|
||||
|
||||
_program->setUniform(_uniformCache.useColormap, useColorMap);
|
||||
@@ -1212,6 +1260,8 @@ void RenderablePointCloud::renderBillboards(const RenderData& data,
|
||||
);
|
||||
}
|
||||
|
||||
_program->setUniform(_uniformCache.useOrientationData, useOrientationData());
|
||||
|
||||
bool useTexture = _hasSpriteTexture && _texture.enabled;
|
||||
_program->setUniform(_uniformCache.hasSpriteTexture, useTexture);
|
||||
|
||||
@@ -1275,7 +1325,7 @@ void RenderablePointCloud::render(const RenderData& data, RendererTasks&) {
|
||||
glm::dvec3 orthoUp = glm::normalize(glm::cross(cameraViewDirectionWorld, orthoRight));
|
||||
|
||||
if (_hasDataFile && _drawElements) {
|
||||
renderBillboards(data, modelMatrix, orthoRight, orthoUp, fadeInVar);
|
||||
renderPoints(data, modelMatrix, orthoRight, orthoUp, fadeInVar);
|
||||
}
|
||||
|
||||
if (_hasLabels) {
|
||||
@@ -1314,10 +1364,52 @@ glm::dvec3 RenderablePointCloud::transformedPosition(
|
||||
return glm::dvec3(_transformationMatrix * position);
|
||||
}
|
||||
|
||||
glm::quat RenderablePointCloud::orientationQuaternion(
|
||||
const dataloader::Dataset::Entry& e) const
|
||||
{
|
||||
const int orientationDataIndex = _dataset.orientationDataIndex;
|
||||
|
||||
const glm::vec3 u = glm::normalize(glm::vec3(
|
||||
_transformationMatrix *
|
||||
glm::dvec4(
|
||||
e.data[orientationDataIndex + 0],
|
||||
e.data[orientationDataIndex + 1],
|
||||
e.data[orientationDataIndex + 2],
|
||||
1.f
|
||||
)
|
||||
));
|
||||
|
||||
const glm::vec3 v = glm::normalize(glm::vec3(
|
||||
_transformationMatrix *
|
||||
glm::dvec4(
|
||||
e.data[orientationDataIndex + 3],
|
||||
e.data[orientationDataIndex + 4],
|
||||
e.data[orientationDataIndex + 5],
|
||||
1.f
|
||||
)
|
||||
));
|
||||
|
||||
// Get the quaternion that represents the rotation from XY plane to the plane that is
|
||||
// spanned by the UV vectors.
|
||||
|
||||
// First rotate to align the z-axis with plane normal
|
||||
const glm::vec3 planeNormal = glm::normalize(glm::cross(u, v));
|
||||
glm::quat q = glm::normalize(glm::rotation(glm::vec3(0.f, 0.f, 1.f), planeNormal));
|
||||
|
||||
// Add rotation around plane normal (rotate new x-axis to u)
|
||||
const glm::vec3 rotatedRight = glm::normalize(
|
||||
glm::vec3(glm::mat4_cast(q) * glm::vec4(1.f, 0.f, 0.f, 1.f))
|
||||
);
|
||||
q = glm::normalize(glm::rotation(rotatedRight, u)) * q;
|
||||
|
||||
return q;
|
||||
}
|
||||
|
||||
int RenderablePointCloud::nAttributesPerPoint() const {
|
||||
int n = 3; // position
|
||||
n += _hasColorMapFile ? 1 : 0;
|
||||
n += _hasDatavarSize ? 1 : 0;
|
||||
n += hasColorData() ? 1 : 0;
|
||||
n += hasSizeData() ? 1 : 0;
|
||||
n += useOrientationData() ? 4 : 0;
|
||||
n += _hasSpriteTexture ? 1 : 0; // texture id
|
||||
return n;
|
||||
}
|
||||
@@ -1370,14 +1462,18 @@ void RenderablePointCloud::updateBufferData() {
|
||||
|
||||
offset = bufferVertexAttribute("in_position", 3, attibutesPerPoint, offset);
|
||||
|
||||
if (_hasColorMapFile) {
|
||||
if (hasColorData()) {
|
||||
offset = bufferVertexAttribute("in_colorParameter", 1, attibutesPerPoint, offset);
|
||||
}
|
||||
|
||||
if (_hasDatavarSize) {
|
||||
if (hasSizeData()) {
|
||||
offset = bufferVertexAttribute("in_scalingParameter", 1, attibutesPerPoint, offset);
|
||||
}
|
||||
|
||||
if (useOrientationData()) {
|
||||
offset = bufferVertexAttribute("in_orientation", 4, attibutesPerPoint, offset);
|
||||
}
|
||||
|
||||
if (_hasSpriteTexture) {
|
||||
offset = bufferVertexAttribute("in_textureLayer", 1, attibutesPerPoint, offset);
|
||||
}
|
||||
@@ -1432,7 +1528,7 @@ int RenderablePointCloud::currentColorParameterIndex() const {
|
||||
_colorSettings.colorMapping->dataColumn;
|
||||
|
||||
if (!_hasColorMapFile || property.options().empty()) {
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return _dataset.index(property.option().description);
|
||||
@@ -1443,12 +1539,32 @@ int RenderablePointCloud::currentSizeParameterIndex() const {
|
||||
_sizeSettings.sizeMapping->parameterOption;
|
||||
|
||||
if (!_hasDatavarSize || property.options().empty()) {
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return _dataset.index(property.option().description);
|
||||
}
|
||||
|
||||
bool RenderablePointCloud::hasColorData() const {
|
||||
const int colorParamIndex = currentColorParameterIndex();
|
||||
return _hasColorMapFile && colorParamIndex >= 0;
|
||||
}
|
||||
|
||||
bool RenderablePointCloud::hasSizeData() const {
|
||||
const int sizeParamIndex = currentSizeParameterIndex();
|
||||
return _hasDatavarSize && sizeParamIndex >= 0;
|
||||
}
|
||||
|
||||
bool RenderablePointCloud::hasMultiTextureData() const {
|
||||
// What datavar is the texture, if any
|
||||
const int textureIdIndex = _dataset.textureDataIndex;
|
||||
return _hasSpriteTexture && textureIdIndex >= 0;
|
||||
}
|
||||
|
||||
bool RenderablePointCloud::useOrientationData() const {
|
||||
return _hasOrientationData && _useRotation;
|
||||
}
|
||||
|
||||
void RenderablePointCloud::addPositionDataForPoint(unsigned int index,
|
||||
std::vector<float>& result,
|
||||
double& maxRadius) const
|
||||
@@ -1470,20 +1586,35 @@ void RenderablePointCloud::addColorAndSizeDataForPoint(unsigned int index,
|
||||
{
|
||||
const dataloader::Dataset::Entry& e = _dataset.entries[index];
|
||||
|
||||
int colorParamIndex = currentColorParameterIndex();
|
||||
if (_hasColorMapFile && colorParamIndex >= 0) {
|
||||
if (hasColorData()) {
|
||||
const int colorParamIndex = currentColorParameterIndex();
|
||||
result.push_back(e.data[colorParamIndex]);
|
||||
}
|
||||
|
||||
int sizeParamIndex = currentSizeParameterIndex();
|
||||
if (_hasDatavarSize && sizeParamIndex >= 0) {
|
||||
if (hasSizeData()) {
|
||||
const int sizeParamIndex = currentSizeParameterIndex();
|
||||
// @TODO: Consider more detailed control over the scaling. Currently the value
|
||||
// is multiplied with the value as is. Should have similar mapping properties
|
||||
// as the color mapping
|
||||
result.push_back(e.data[sizeParamIndex]);
|
||||
|
||||
// Convert to diameter if data is given as radius
|
||||
float multiplier = _sizeSettings.sizeMapping->isRadius ? 2.f : 1.f;
|
||||
result.push_back(multiplier * e.data[sizeParamIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderablePointCloud::addOrientationDataForPoint(unsigned int index,
|
||||
std::vector<float>& result) const
|
||||
{
|
||||
const dataloader::Dataset::Entry& e = _dataset.entries[index];
|
||||
glm::quat q = orientationQuaternion(e);
|
||||
|
||||
result.push_back(q.x);
|
||||
result.push_back(q.y);
|
||||
result.push_back(q.z);
|
||||
result.push_back(q.w);
|
||||
}
|
||||
|
||||
std::vector<float> RenderablePointCloud::createDataSlice() {
|
||||
ZoneScoped;
|
||||
|
||||
@@ -1491,9 +1622,6 @@ std::vector<float> RenderablePointCloud::createDataSlice() {
|
||||
return std::vector<float>();
|
||||
}
|
||||
|
||||
// What datavar is the texture, if any
|
||||
int textureIdIndex = _dataset.textureDataIndex;
|
||||
|
||||
double maxRadius = 0.0;
|
||||
|
||||
// One sub-array per texture array, since each of these will correspond to a separate
|
||||
@@ -1511,13 +1639,14 @@ std::vector<float> RenderablePointCloud::createDataSlice() {
|
||||
const dataloader::Dataset::Entry& e = _dataset.entries[i];
|
||||
|
||||
unsigned int subresultIndex = 0;
|
||||
// Default texture layer for single texture is zero
|
||||
float textureLayer = 0.f;
|
||||
|
||||
bool useMultiTexture = (_textureMode == TextureInputMode::Multi) &&
|
||||
(textureIdIndex >= 0);
|
||||
hasMultiTextureData();
|
||||
|
||||
if (_hasSpriteTexture && useMultiTexture) {
|
||||
int texId = static_cast<int>(e.data[textureIdIndex]);
|
||||
if (useMultiTexture) {
|
||||
int texId = static_cast<int>(e.data[_dataset.textureDataIndex]);
|
||||
size_t texIndex = _indexInDataToTextureIndex[texId];
|
||||
textureLayer = static_cast<float>(
|
||||
_textureIndexToArrayMap[texIndex].layer
|
||||
@@ -1531,6 +1660,10 @@ std::vector<float> RenderablePointCloud::createDataSlice() {
|
||||
addPositionDataForPoint(i, subArrayToUse, maxRadius);
|
||||
addColorAndSizeDataForPoint(i, subArrayToUse);
|
||||
|
||||
if (useOrientationData()) {
|
||||
addOrientationDataForPoint(i, subArrayToUse);
|
||||
}
|
||||
|
||||
// Texture layer
|
||||
if (_hasSpriteTexture) {
|
||||
subArrayToUse.push_back(static_cast<float>(textureLayer));
|
||||
|
||||
@@ -98,6 +98,7 @@ protected:
|
||||
virtual void preUpdate();
|
||||
|
||||
glm::dvec3 transformedPosition(const dataloader::Dataset::Entry& e) const;
|
||||
glm::quat orientationQuaternion(const dataloader::Dataset::Entry& e) const;
|
||||
|
||||
virtual int nAttributesPerPoint() const;
|
||||
|
||||
@@ -118,10 +119,17 @@ protected:
|
||||
/// Find the index of the currently chosen size parameter in the dataset
|
||||
int currentSizeParameterIndex() const;
|
||||
|
||||
bool hasColorData() const;
|
||||
bool hasSizeData() const;
|
||||
bool hasMultiTextureData() const;
|
||||
bool useOrientationData() const;
|
||||
|
||||
virtual void addPositionDataForPoint(unsigned int index, std::vector<float>& result,
|
||||
double& maxRadius) const;
|
||||
virtual void addColorAndSizeDataForPoint(unsigned int index,
|
||||
std::vector<float>& result) const;
|
||||
virtual void addOrientationDataForPoint(unsigned int index,
|
||||
std::vector<float>& result) const;
|
||||
|
||||
std::vector<float> createDataSlice();
|
||||
|
||||
@@ -146,7 +154,7 @@ protected:
|
||||
|
||||
float computeDistanceFadeValue(const RenderData& data) const;
|
||||
|
||||
void renderBillboards(const RenderData& data, const glm::dmat4& modelMatrix,
|
||||
void renderPoints(const RenderData& data, const glm::dmat4& modelMatrix,
|
||||
const glm::dvec3& orthoRight, const glm::dvec3& orthoUp, float fadeInVariable);
|
||||
|
||||
gl::GLenum internalGlFormat(bool useAlpha) const;
|
||||
@@ -194,11 +202,13 @@ protected:
|
||||
Fading _fading;
|
||||
|
||||
properties::BoolProperty _useAdditiveBlending;
|
||||
properties::BoolProperty _useRotation;
|
||||
|
||||
properties::BoolProperty _drawElements;
|
||||
properties::OptionProperty _renderOption;
|
||||
|
||||
properties::UIntProperty _nDataPoints;
|
||||
properties::BoolProperty _hasOrientationData;
|
||||
|
||||
struct Texture : properties::PropertyOwner {
|
||||
Texture();
|
||||
@@ -221,7 +231,7 @@ protected:
|
||||
cmapRangeMin, cmapRangeMax, nanColor, useNanColor, hideOutsideRange,
|
||||
enableMaxSizeControl, aboveRangeColor, useAboveRangeColor, belowRangeColor,
|
||||
useBelowRangeColor, hasDvarScaling, dvarScaleFactor, enableOutline, outlineColor,
|
||||
outlineWeight, aspectRatioScale
|
||||
outlineWeight, aspectRatioScale, useOrientationData
|
||||
) _uniformCache;
|
||||
|
||||
std::filesystem::path _dataFile;
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <modules/base/rendering/pointcloud/sizemappingcomponent.h>
|
||||
|
||||
#include <openspace/documentation/documentation.h>
|
||||
#include <openspace/util/distanceconversion.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
|
||||
namespace {
|
||||
@@ -57,6 +58,14 @@ namespace {
|
||||
openspace::properties::Property::Visibility::AdvancedUser
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo IsRadiusInfo = {
|
||||
"IsRadius",
|
||||
"Size is Radius",
|
||||
"If true, the size value in the data is interpreted as the radius of the points. "
|
||||
"Otherwise, it is interpreted as the diameter.",
|
||||
openspace::properties::Property::Visibility::AdvancedUser
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(SizeMappingComponent)]] Parameters {
|
||||
// [[codegen::verbatim(EnabledInfo.description)]]
|
||||
std::optional<bool> enabled;
|
||||
@@ -69,7 +78,36 @@ namespace {
|
||||
std::optional<std::string> parameter;
|
||||
|
||||
// [[codegen::verbatim(ScaleFactorInfo.description)]]
|
||||
std::optional<float> scaleFactor;
|
||||
enum class [[codegen::map(openspace::DistanceUnit)]] ScaleUnit {
|
||||
Nanometer,
|
||||
Micrometer,
|
||||
Millimeter,
|
||||
Centimeter,
|
||||
Decimeter,
|
||||
Meter,
|
||||
Kilometer,
|
||||
AU,
|
||||
Lighthour,
|
||||
Lightday,
|
||||
Lightmonth,
|
||||
Lightyear,
|
||||
Parsec,
|
||||
Kiloparsec,
|
||||
Megaparsec,
|
||||
Gigaparsec,
|
||||
Gigalightyear
|
||||
};
|
||||
|
||||
// The scale to use for the size values in the dataset, given as either a string
|
||||
// representing a specific unit or a value to multiply all the datapoints with
|
||||
// to convert the value to meter. The resulting value will be applied as a
|
||||
// multiplicative factor. For example, if the size data is given in is in
|
||||
// kilometers then specify either <code>ScaleFactor = 'Kilometer'</code> or
|
||||
// <code>ScaleFactor = 1000.0</code>.
|
||||
std::optional<std::variant<ScaleUnit, double>> scaleFactor;
|
||||
|
||||
// [[codegen::verbatim(IsRadiusInfo.description)]]
|
||||
std::optional<bool> isRadius;
|
||||
};
|
||||
#include "sizemappingcomponent_codegen.cpp"
|
||||
} // namespace
|
||||
@@ -88,10 +126,12 @@ SizeMappingComponent::SizeMappingComponent()
|
||||
properties::OptionProperty::DisplayType::Dropdown
|
||||
)
|
||||
, scaleFactor(ScaleFactorInfo, 1.f, 0.f, 1000.f)
|
||||
, isRadius(IsRadiusInfo, false)
|
||||
{
|
||||
addProperty(enabled);
|
||||
addProperty(parameterOption);
|
||||
addProperty(scaleFactor);
|
||||
addProperty(isRadius);
|
||||
}
|
||||
|
||||
SizeMappingComponent::SizeMappingComponent(const ghoul::Dictionary& dictionary)
|
||||
@@ -125,7 +165,19 @@ SizeMappingComponent::SizeMappingComponent(const ghoul::Dictionary& dictionary)
|
||||
));
|
||||
}
|
||||
|
||||
scaleFactor = p.scaleFactor.value_or(scaleFactor);
|
||||
if (p.scaleFactor.has_value()) {
|
||||
if (std::holds_alternative<Parameters::ScaleUnit>(*p.scaleFactor)) {
|
||||
const Parameters::ScaleUnit scaleUnit =
|
||||
std::get<Parameters::ScaleUnit>(*p.scaleFactor);
|
||||
const DistanceUnit distanceUnit = codegen::map<DistanceUnit>(scaleUnit);
|
||||
scaleFactor = toMeter(distanceUnit);
|
||||
}
|
||||
else if (std::holds_alternative<double>(*p.scaleFactor)) {
|
||||
scaleFactor = std::get<double>(*p.scaleFactor);
|
||||
}
|
||||
}
|
||||
|
||||
isRadius = p.isRadius.value_or(isRadius);
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -49,6 +49,7 @@ struct SizeMappingComponent : public properties::PropertyOwner {
|
||||
properties::BoolProperty enabled;
|
||||
properties::OptionProperty parameterOption;
|
||||
properties::FloatProperty scaleFactor;
|
||||
properties::BoolProperty isRadius;
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -103,9 +103,6 @@ Fragment getFragment() {
|
||||
}
|
||||
|
||||
fullColor.a *= opacity * fadeInValue;
|
||||
if (fullColor.a < 0.01) {
|
||||
discard;
|
||||
}
|
||||
|
||||
Fragment frag;
|
||||
frag.color = fullColor;
|
||||
@@ -30,6 +30,7 @@ layout(points) in;
|
||||
flat in float textureLayer[];
|
||||
flat in float colorParameter[];
|
||||
flat in float scalingParameter[];
|
||||
flat in vec4 orientation[]; // quaternion
|
||||
|
||||
layout(triangle_strip, max_vertices = 4) out;
|
||||
flat out float gs_colorParameter;
|
||||
@@ -48,6 +49,7 @@ uniform dmat4 modelMatrix;
|
||||
uniform bool enableMaxSizeControl;
|
||||
uniform bool hasDvarScaling;
|
||||
uniform float dvarScaleFactor;
|
||||
uniform bool useOrientationData;
|
||||
|
||||
// RenderOption: CameraViewDirection
|
||||
uniform vec3 up;
|
||||
@@ -72,6 +74,24 @@ const vec2 corners[4] = vec2[4](
|
||||
|
||||
const int RenderOptionCameraViewDirection = 0;
|
||||
const int RenderOptionCameraPositionNormal = 1;
|
||||
const int RenderOptionFixedRotation = 2;
|
||||
|
||||
// Quaternion math code from:
|
||||
// https://gist.github.com/mattatz/40a91588d5fb38240403f198a938a593
|
||||
|
||||
vec4 quatMult(vec4 q1, vec4 q2) {
|
||||
return vec4(
|
||||
q2.xyz * q1.w + q1.xyz * q2.w + cross(q1.xyz, q2.xyz),
|
||||
q1.w * q2.w - dot(q1.xyz, q2.xyz)
|
||||
);
|
||||
}
|
||||
|
||||
// Vector rotation with a quaternion
|
||||
// http://mathworld.wolfram.com/Quaternion.html
|
||||
vec3 rotate_vector(vec3 v, vec4 q) {
|
||||
vec4 q_conjugate = q * vec4(-1.0, -1.0, -1.0, 1.0);
|
||||
return quatMult(q, quatMult(vec4(v, 0.0), q_conjugate)).xyz;
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec4 pos = gl_in[0].gl_Position;
|
||||
@@ -85,21 +105,32 @@ void main() {
|
||||
scaleMultiply *= scalingParameter[0] * dvarScaleFactor;
|
||||
}
|
||||
|
||||
vec3 scaledRight = vec3(0.0);
|
||||
vec3 scaledUp = vec3(0.0);
|
||||
vec3 scaledRight = vec3(1.0, 0.0, 0.0);
|
||||
vec3 scaledUp = vec3(0.0, 1.0, 0.0);
|
||||
|
||||
if (renderOption == RenderOptionCameraViewDirection) {
|
||||
scaledRight = scaleMultiply * right * 0.5;
|
||||
scaledUp = scaleMultiply * up * 0.5;
|
||||
scaledRight = right;
|
||||
scaledUp = up;
|
||||
}
|
||||
else if (renderOption == RenderOptionCameraPositionNormal) {
|
||||
vec3 normal = vec3(normalize(cameraPosition - dpos.xyz));
|
||||
vec3 newRight = normalize(cross(cameraLookUp, normal));
|
||||
vec3 newUp = cross(normal, newRight);
|
||||
|
||||
scaledRight = scaleMultiply * newRight * 0.5;
|
||||
scaledUp = scaleMultiply * newUp * 0.5;
|
||||
scaledRight = newRight;
|
||||
scaledUp = newUp;
|
||||
}
|
||||
else if (renderOption == RenderOptionFixedRotation) {
|
||||
if (useOrientationData) {
|
||||
vec4 quat = orientation[0];
|
||||
scaledRight = normalize(rotate_vector(scaledRight, quat));
|
||||
scaledUp = normalize(rotate_vector(scaledUp, quat));
|
||||
}
|
||||
// Else use default
|
||||
}
|
||||
|
||||
scaledRight *= scaleMultiply * 0.5;
|
||||
scaledUp *= scaleMultiply * 0.5;
|
||||
|
||||
if (enableMaxSizeControl) {
|
||||
// Limit the max size of the points, as the angle in "FOV" that the point is allowed
|
||||
@@ -40,6 +40,9 @@ in float in_scalingParameter1;
|
||||
|
||||
in float in_textureLayer;
|
||||
|
||||
in vec4 in_orientation0; // quaternion
|
||||
in vec4 in_orientation1; // quaternion
|
||||
|
||||
uniform bool useSpline;
|
||||
uniform float interpolationValue;
|
||||
|
||||
@@ -47,6 +50,8 @@ flat out float textureLayer;
|
||||
flat out float colorParameter;
|
||||
flat out float scalingParameter;
|
||||
|
||||
flat out vec4 orientation; // quaternion
|
||||
|
||||
float interpolateDataValue(float v0, float v1, float t) {
|
||||
const float Epsilon = 1E-7;
|
||||
const float NaN = log(-1.0); // undefined
|
||||
@@ -73,6 +78,53 @@ vec3 interpolateCatmullRom(float t, vec3 p0, vec3 p1, vec3 p2, vec3 p3) {
|
||||
);
|
||||
}
|
||||
|
||||
// Quaternion math from: https://gist.github.com/mattatz/40a91588d5fb38240403f198a938a593
|
||||
vec4 quaternionSlerp(vec4 a, vec4 b, float t) {
|
||||
// if either input is zero, return the other.
|
||||
if (length(a) == 0.0) {
|
||||
if (length(b) == 0.0) {
|
||||
return vec4(0.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
return b;
|
||||
}
|
||||
else if (length(b) == 0.0) {
|
||||
return a;
|
||||
}
|
||||
|
||||
float cosHalfAngle = a.w * b.w + dot(a.xyz, b.xyz);
|
||||
|
||||
if (cosHalfAngle >= 1.0 || cosHalfAngle <= -1.0) {
|
||||
return a;
|
||||
}
|
||||
else if (cosHalfAngle < 0.0) {
|
||||
b.xyz = -b.xyz;
|
||||
b.w = -b.w;
|
||||
cosHalfAngle = -cosHalfAngle;
|
||||
}
|
||||
|
||||
float blendA;
|
||||
float blendB;
|
||||
if (cosHalfAngle < 0.99) {
|
||||
// Do proper slerp for big angles
|
||||
float halfAngle = acos(cosHalfAngle);
|
||||
float sinHalfAngle = sin(halfAngle);
|
||||
float oneOverSinHalfAngle = 1.0 / sinHalfAngle;
|
||||
blendA = sin(halfAngle * (1.0 - t)) * oneOverSinHalfAngle;
|
||||
blendB = sin(halfAngle * t) * oneOverSinHalfAngle;
|
||||
}
|
||||
else {
|
||||
// Do lerp if angle is really small
|
||||
blendA = 1.0 - t;
|
||||
blendB = t;
|
||||
}
|
||||
|
||||
vec4 result = vec4(blendA * a.xyz + blendB * b.xyz, blendA * a.w + blendB * b.w);
|
||||
if (length(result) > 0.0) {
|
||||
return normalize(result);
|
||||
}
|
||||
return vec4(0.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
void main() {
|
||||
float t = interpolationValue;
|
||||
|
||||
@@ -90,6 +142,8 @@ void main() {
|
||||
);
|
||||
}
|
||||
|
||||
orientation = quaternionSlerp(in_orientation0, in_orientation1, t);
|
||||
|
||||
textureLayer = in_textureLayer;
|
||||
|
||||
gl_Position = vec4(position, 1.0);
|
||||
@@ -30,14 +30,17 @@ in vec3 in_position;
|
||||
in float in_textureLayer;
|
||||
in float in_colorParameter;
|
||||
in float in_scalingParameter;
|
||||
in vec4 in_orientation; // quaternion
|
||||
|
||||
flat out float textureLayer;
|
||||
flat out float colorParameter;
|
||||
flat out float scalingParameter;
|
||||
flat out vec4 orientation; // quaternion
|
||||
|
||||
void main() {
|
||||
textureLayer = in_textureLayer;
|
||||
colorParameter = in_colorParameter;
|
||||
scalingParameter = in_scalingParameter;
|
||||
orientation = in_orientation;
|
||||
gl_Position = vec4(in_position, 1.0);
|
||||
}
|
||||
@@ -26,13 +26,11 @@ include(${PROJECT_SOURCE_DIR}/support/cmake/module_definition.cmake)
|
||||
|
||||
set(HEADER_FILES
|
||||
rendering/renderabledumeshes.h
|
||||
rendering/renderableplanescloud.h
|
||||
)
|
||||
source_group("Header Files" FILES ${HEADER_FILES})
|
||||
|
||||
set(SOURCE_FILES
|
||||
rendering/renderabledumeshes.cpp
|
||||
rendering/renderableplanescloud.cpp
|
||||
)
|
||||
source_group("Source Files" FILES ${SOURCE_FILES})
|
||||
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
#include <modules/digitaluniverse/digitaluniversemodule.h>
|
||||
|
||||
#include <modules/digitaluniverse/rendering/renderabledumeshes.h>
|
||||
#include <modules/digitaluniverse/rendering/renderableplanescloud.h>
|
||||
#include <openspace/documentation/documentation.h>
|
||||
#include <openspace/rendering/renderable.h>
|
||||
#include <openspace/util/factorymanager.h>
|
||||
@@ -46,7 +45,6 @@ void DigitalUniverseModule::internalInitialize(const ghoul::Dictionary&) {
|
||||
FactoryManager::ref().factory<Renderable>();
|
||||
ghoul_assert(fRenderable, "Renderable factory was not created");
|
||||
|
||||
fRenderable->registerClass<RenderablePlanesCloud>("RenderablePlanesCloud");
|
||||
fRenderable->registerClass<RenderableDUMeshes>("RenderableDUMeshes");
|
||||
}
|
||||
|
||||
@@ -57,7 +55,6 @@ void DigitalUniverseModule::internalDeinitializeGL() {
|
||||
|
||||
std::vector<documentation::Documentation> DigitalUniverseModule::documentations() const {
|
||||
return {
|
||||
RenderablePlanesCloud::Documentation(),
|
||||
RenderableDUMeshes::Documentation()
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,669 +0,0 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2024 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
|
||||
* software and associated documentation files (the "Software"), to deal in the Software *
|
||||
* without restriction, including without limitation the rights to use, copy, modify, *
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
|
||||
* permit persons to whom the Software is furnished to do so, subject to the following *
|
||||
* conditions: *
|
||||
* *
|
||||
* The above copyright notice and this permission notice shall be included in all copies *
|
||||
* or substantial portions of the Software. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#include <modules/digitaluniverse/rendering/renderableplanescloud.h>
|
||||
|
||||
#include <modules/digitaluniverse/digitaluniversemodule.h>
|
||||
#include <openspace/documentation/documentation.h>
|
||||
#include <openspace/documentation/verifier.h>
|
||||
#include <openspace/engine/globals.h>
|
||||
#include <openspace/rendering/renderengine.h>
|
||||
#include <openspace/util/updatestructures.h>
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <ghoul/io/texture/texturereader.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/misc/profiling.h>
|
||||
#include <ghoul/opengl/openglstatecache.h>
|
||||
#include <ghoul/opengl/programobject.h>
|
||||
#include <ghoul/opengl/texture.h>
|
||||
#include <ghoul/opengl/textureunit.h>
|
||||
#include <array>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
namespace {
|
||||
constexpr std::string_view _loggerCat = "RenderablePlanesCloud";
|
||||
|
||||
constexpr int PlanesVertexDataSize = 36;
|
||||
|
||||
constexpr std::array<const char*, 4> UniformNames = {
|
||||
"modelViewProjectionTransform", "alphaValue", "fadeInValue", "galaxyTexture"
|
||||
};
|
||||
|
||||
enum BlendMode {
|
||||
BlendModeNormal = 0,
|
||||
BlendModeAdditive
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo ScaleFactorInfo = {
|
||||
"ScaleFactor",
|
||||
"Scale Factor",
|
||||
"This value is used as a multiplicative factor that is applied to the apparent "
|
||||
"size of each point",
|
||||
// @VISIBILITY(2.5)
|
||||
openspace::properties::Property::Visibility::User
|
||||
};
|
||||
|
||||
static const openspace::properties::PropertyOwner::PropertyOwnerInfo LabelsInfo = {
|
||||
"Labels",
|
||||
"Labels",
|
||||
"The labels for the astronomical objects"
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo DrawElementsInfo = {
|
||||
"DrawElements",
|
||||
"Draw Elements",
|
||||
"Enables/Disables the drawing of the astronomical objects",
|
||||
openspace::properties::Property::Visibility::NoviceUser
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo TransformationMatrixInfo = {
|
||||
"TransformationMatrix",
|
||||
"Transformation Matrix",
|
||||
"Transformation matrix to be applied to each astronomical object",
|
||||
openspace::properties::Property::Visibility::Developer
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo BlendModeInfo = {
|
||||
"BlendMode",
|
||||
"Blending Mode",
|
||||
"This determines the blending mode that is applied to this plane",
|
||||
openspace::properties::Property::Visibility::AdvancedUser
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo TexturePathInfo = {
|
||||
"TexturePath",
|
||||
"Texture Path",
|
||||
"This value specifies the path for the textures in disk",
|
||||
openspace::properties::Property::Visibility::AdvancedUser
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo LuminosityInfo = {
|
||||
"Luminosity",
|
||||
"Luminosity variable",
|
||||
"Datavar variable to control the luminosity/size of the astronomical objects",
|
||||
// @VISIBILITY(2.67)
|
||||
openspace::properties::Property::Visibility::User
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo ScaleLuminosityInfo = {
|
||||
"ScaleLuminosity",
|
||||
"ScaleLuminosity variable",
|
||||
"Scaling control for the luminosity/size of the astronomical objects",
|
||||
// @VISIBILITY(2.67)
|
||||
openspace::properties::Property::Visibility::User
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo RenderOptionInfo = {
|
||||
"RenderOption",
|
||||
"Render Option",
|
||||
"Debug option for rendering of billboards and texts",
|
||||
openspace::properties::Property::Visibility::AdvancedUser
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo FadeInDistancesInfo = {
|
||||
"FadeInDistances",
|
||||
"Fade-In Start and End Distances",
|
||||
"These values determine the initial and final distances from the center of "
|
||||
"our galaxy from which the astronomical object will start and end fading-in",
|
||||
openspace::properties::Property::Visibility::AdvancedUser
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo DisableFadeInInfo = {
|
||||
"DisableFadeIn",
|
||||
"Disable Fade-in effect",
|
||||
"Enables/Disables the Fade-in effect",
|
||||
openspace::properties::Property::Visibility::User
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo PlaneMinSizeInfo = {
|
||||
"PlaneMinSize",
|
||||
"Plane Min Size in Pixels",
|
||||
"The min size (in pixels) for the plane representing the astronomical object",
|
||||
openspace::properties::Property::Visibility::AdvancedUser
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(RenderablePlanesCloud)]] Parameters {
|
||||
// The path to the SPECK file that contains information about the astronomical
|
||||
// object being rendered
|
||||
std::optional<std::string> file;
|
||||
|
||||
// [[codegen::verbatim(ScaleFactorInfo.description)]]
|
||||
std::optional<float> scaleFactor;
|
||||
|
||||
// [[codegen::verbatim(LabelsInfo.description)]]
|
||||
std::optional<ghoul::Dictionary> labels
|
||||
[[codegen::reference("labelscomponent")]];
|
||||
|
||||
// [[codegen::verbatim(TransformationMatrixInfo.description)]]
|
||||
std::optional<glm::dmat4x4> transformationMatrix;
|
||||
|
||||
enum class BlendMode {
|
||||
Normal,
|
||||
Additive
|
||||
};
|
||||
|
||||
// [[codegen::verbatim(BlendModeInfo.description)]]
|
||||
std::optional<BlendMode> blendMode;
|
||||
|
||||
enum class [[codegen::map(openspace::DistanceUnit)]] Unit {
|
||||
Meter [[codegen::key("m")]],
|
||||
Kilometer [[codegen::key("Km")]],
|
||||
Parsec [[codegen::key("pc")]],
|
||||
Kiloparsec [[codegen::key("Kpc")]],
|
||||
Megaparsec [[codegen::key("Mpc")]],
|
||||
Gigaparsec [[codegen::key("Gpc")]],
|
||||
Gigalightyear [[codegen::key("Gly")]]
|
||||
};
|
||||
std::optional<Unit> unit;
|
||||
|
||||
// [[codegen::verbatim(TexturePathInfo.description)]]
|
||||
std::string texturePath;
|
||||
|
||||
// [[codegen::verbatim(LuminosityInfo.description)]]
|
||||
std::optional<std::string> luminosity;
|
||||
|
||||
// [[codegen::verbatim(ScaleLuminosityInfo.description)]]
|
||||
std::optional<float> scaleLuminosity;
|
||||
|
||||
// [[codegen::verbatim(FadeInDistancesInfo.description)]]
|
||||
std::optional<glm::vec2> fadeInDistances;
|
||||
|
||||
// [[codegen::verbatim(DisableFadeInInfo.description)]]
|
||||
std::optional<bool> disableFadeIn;
|
||||
|
||||
// [[codegen::verbatim(PlaneMinSizeInfo.description)]]
|
||||
std::optional<float> planeMinSize;
|
||||
};
|
||||
#include "renderableplanescloud_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation RenderablePlanesCloud::Documentation() {
|
||||
return codegen::doc<Parameters>("digitaluniverse_RenderablePlanesCloud");
|
||||
}
|
||||
|
||||
RenderablePlanesCloud::RenderablePlanesCloud(const ghoul::Dictionary& dictionary)
|
||||
: Renderable(dictionary)
|
||||
, _scaleFactor(ScaleFactorInfo, 1.f, 0.f, 1000.f)
|
||||
, _drawElements(DrawElementsInfo, true)
|
||||
, _blendMode(BlendModeInfo, properties::OptionProperty::DisplayType::Dropdown)
|
||||
, _fadeInDistances(
|
||||
FadeInDistancesInfo,
|
||||
glm::vec2(0.f),
|
||||
glm::vec2(0.f),
|
||||
glm::vec2(200000.f)
|
||||
)
|
||||
, _disableFadeInDistance(DisableFadeInInfo, true)
|
||||
, _planeMinSize(PlaneMinSizeInfo, 0.5, 0.0, 500.0)
|
||||
, _renderOption(RenderOptionInfo, properties::OptionProperty::DisplayType::Dropdown)
|
||||
{
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
addProperty(Fadeable::_opacity);
|
||||
|
||||
if (p.file.has_value()) {
|
||||
_speckFile = absPath(*p.file);
|
||||
_hasSpeckFile = true;
|
||||
_drawElements.onChange([this]() { _hasSpeckFile = !_hasSpeckFile; });
|
||||
addProperty(_drawElements);
|
||||
}
|
||||
|
||||
// DEBUG:
|
||||
_renderOption.addOption(0, "Camera View Direction");
|
||||
_renderOption.addOption(1, "Camera Position Normal");
|
||||
_renderOption.addOption(2, "Screen center Position Normal");
|
||||
addProperty(_renderOption);
|
||||
//_renderOption = 1;
|
||||
|
||||
if (p.unit.has_value()) {
|
||||
_unit = codegen::map<DistanceUnit>(*p.unit);
|
||||
}
|
||||
else {
|
||||
_unit = DistanceUnit::Meter;
|
||||
}
|
||||
|
||||
_scaleFactor = p.scaleFactor.value_or(_scaleFactor);
|
||||
addProperty(_scaleFactor);
|
||||
_scaleFactor.onChange([this]() { _dataIsDirty = true; });
|
||||
|
||||
if (p.labels.has_value()) {
|
||||
_labels = std::make_unique<LabelsComponent>(*p.labels);
|
||||
_hasLabels = true;
|
||||
addPropertySubOwner(_labels.get());
|
||||
// Fading of the labels should also depend on the fading of the renderable
|
||||
_labels->setParentFadeable(this);
|
||||
}
|
||||
|
||||
_transformationMatrix = p.transformationMatrix.value_or(_transformationMatrix);
|
||||
|
||||
_blendMode.addOptions({
|
||||
{ BlendModeNormal, "Normal" },
|
||||
{ BlendModeAdditive, "Additive" }
|
||||
});
|
||||
_blendMode.onChange([this]() {
|
||||
BlendMode m = static_cast<BlendMode>(_blendMode.value());
|
||||
switch (m) {
|
||||
case BlendModeNormal:
|
||||
setRenderBin(Renderable::RenderBin::Opaque);
|
||||
break;
|
||||
case BlendModeAdditive:
|
||||
setRenderBin(Renderable::RenderBin::PreDeferredTransparent);
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
if (p.blendMode.has_value()) {
|
||||
switch (*p.blendMode) {
|
||||
case Parameters::BlendMode::Normal:
|
||||
_blendMode = BlendModeNormal;
|
||||
break;
|
||||
case Parameters::BlendMode::Additive:
|
||||
_blendMode = BlendModeAdditive;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_texturesPath = absPath(p.texturePath);
|
||||
|
||||
_luminosityVar = p.luminosity.value_or(_luminosityVar);
|
||||
_sluminosity = p.scaleLuminosity.value_or(_sluminosity);
|
||||
|
||||
if (p.fadeInDistances.has_value()) {
|
||||
_fadeInDistances = *p.fadeInDistances;
|
||||
_disableFadeInDistance = false;
|
||||
_fadeInDistances.setViewOption(properties::Property::ViewOptions::MinMaxRange);
|
||||
addProperty(_fadeInDistances);
|
||||
addProperty(_disableFadeInDistance);
|
||||
}
|
||||
|
||||
_planeMinSize = p.planeMinSize.value_or(_planeMinSize);
|
||||
|
||||
if (p.planeMinSize.has_value()) {
|
||||
addProperty(_planeMinSize);
|
||||
}
|
||||
}
|
||||
|
||||
bool RenderablePlanesCloud::isReady() const {
|
||||
bool isReady = _program && !_dataset.entries.empty();
|
||||
|
||||
// If we have labels, they also need to be loaded
|
||||
if (_hasLabels) {
|
||||
isReady = isReady || _labels->isReady();
|
||||
}
|
||||
return isReady;
|
||||
}
|
||||
|
||||
void RenderablePlanesCloud::initialize() {
|
||||
ZoneScoped;
|
||||
|
||||
if (_hasSpeckFile && std::filesystem::is_regular_file(_speckFile)) {
|
||||
_dataset = dataloader::data::loadFileWithCache(_speckFile);
|
||||
if (_dataset.entries.empty()) {
|
||||
throw ghoul::RuntimeError("Error loading data");
|
||||
}
|
||||
}
|
||||
|
||||
if (_hasLabels) {
|
||||
_labels->initialize();
|
||||
}
|
||||
}
|
||||
|
||||
void RenderablePlanesCloud::initializeGL() {
|
||||
ZoneScoped;
|
||||
|
||||
_program = DigitalUniverseModule::ProgramObjectManager.request(
|
||||
"RenderablePlanesCloud",
|
||||
[]() -> std::unique_ptr<ghoul::opengl::ProgramObject> {
|
||||
return global::renderEngine->buildRenderProgram(
|
||||
"RenderablePlanesCloud",
|
||||
absPath("${MODULE_DIGITALUNIVERSE}/shaders/plane_vs.glsl"),
|
||||
absPath("${MODULE_DIGITALUNIVERSE}/shaders/plane_fs.glsl")
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
ghoul::opengl::updateUniformLocations(*_program, _uniformCache, UniformNames);
|
||||
|
||||
createPlanes();
|
||||
loadTextures();
|
||||
}
|
||||
|
||||
void RenderablePlanesCloud::deleteDataGPUAndCPU() {
|
||||
for (std::unordered_map<int, PlaneAggregate>::reference pAMapItem : _planesMap) {
|
||||
glDeleteBuffers(1, &pAMapItem.second.vbo);
|
||||
glDeleteVertexArrays(1, &pAMapItem.second.vao);
|
||||
pAMapItem.second.planesCoordinates.clear();
|
||||
}
|
||||
_planesMap.clear();
|
||||
}
|
||||
|
||||
void RenderablePlanesCloud::deinitializeGL() {
|
||||
deleteDataGPUAndCPU();
|
||||
|
||||
DigitalUniverseModule::ProgramObjectManager.release(
|
||||
"RenderablePlanesCloud",
|
||||
[](ghoul::opengl::ProgramObject* p) {
|
||||
global::renderEngine->removeRenderProgram(p);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
void RenderablePlanesCloud::renderPlanes(const RenderData&,
|
||||
const glm::dmat4& modelViewTransform,
|
||||
const glm::dmat4& projectionTransform,
|
||||
const float fadeInVariable)
|
||||
{
|
||||
glEnablei(GL_BLEND, 0);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
||||
//glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glDepthMask(false);
|
||||
|
||||
_program->activate();
|
||||
|
||||
glm::dmat4 modelViewProjectionTransform =
|
||||
glm::dmat4(projectionTransform) * modelViewTransform;
|
||||
_program->setUniform(
|
||||
_uniformCache.modelViewProjectionTransform,
|
||||
modelViewProjectionTransform
|
||||
);
|
||||
_program->setUniform(_uniformCache.alphaValue, opacity());
|
||||
_program->setUniform(_uniformCache.fadeInValue, fadeInVariable);
|
||||
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
GLint viewport[4];
|
||||
global::renderEngine->openglStateCache().viewport(viewport);
|
||||
|
||||
ghoul::opengl::TextureUnit unit;
|
||||
unit.activate();
|
||||
_program->setUniform(_uniformCache.galaxyTexture, unit);
|
||||
int currentTextureIndex = -1;
|
||||
|
||||
for (std::unordered_map<int, PlaneAggregate>::reference pAMapItem : _planesMap) {
|
||||
// For planes with undefined textures references
|
||||
if (pAMapItem.first == 30) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// We only bind a new texture when it is needed
|
||||
if (currentTextureIndex != pAMapItem.first) {
|
||||
_textureMap[pAMapItem.first]->bind();
|
||||
currentTextureIndex = pAMapItem.first;
|
||||
}
|
||||
glBindVertexArray(pAMapItem.second.vao);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6 * pAMapItem.second.numberOfPlanes);
|
||||
}
|
||||
|
||||
glBindVertexArray(0);
|
||||
_program->deactivate();
|
||||
|
||||
// Restores OpenGL Rendering State
|
||||
global::renderEngine->openglStateCache().resetBlendState();
|
||||
global::renderEngine->openglStateCache().resetDepthState();
|
||||
global::renderEngine->openglStateCache().resetPolygonAndClippingState();
|
||||
}
|
||||
|
||||
void RenderablePlanesCloud::render(const RenderData& data, RendererTasks&) {
|
||||
const double scale = toMeter(_unit);
|
||||
|
||||
float fadeInVariable = 1.f;
|
||||
if (!_disableFadeInDistance) {
|
||||
float distCamera = static_cast<float>(glm::length(data.camera.positionVec3()));
|
||||
distCamera = static_cast<float>(distCamera / scale);
|
||||
const glm::vec2 fadeRange = _fadeInDistances;
|
||||
//const float a = 1.f / ((fadeRange.y - fadeRange.x) * scale);
|
||||
const float a = 1.f / ((fadeRange.y - fadeRange.x));
|
||||
const float b = -(fadeRange.x / (fadeRange.y - fadeRange.x));
|
||||
const float funcValue = a * distCamera + b;
|
||||
fadeInVariable *= funcValue > 1.f ? 1.f : funcValue;
|
||||
|
||||
if (funcValue < 0.01f) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const glm::dmat4 modelTransform = calcModelTransform(data);
|
||||
const glm::dmat4 modelViewTransform = calcModelViewTransform(data, modelTransform);
|
||||
const glm::mat4 projectionTransform = data.camera.projectionMatrix();
|
||||
|
||||
if (_hasSpeckFile) {
|
||||
renderPlanes(data, modelViewTransform, projectionTransform, fadeInVariable);
|
||||
}
|
||||
|
||||
if (_hasLabels) {
|
||||
const glm::dmat4 modelViewProjectionTransform =
|
||||
glm::dmat4(projectionTransform) * modelViewTransform;
|
||||
|
||||
const glm::dmat4 invMVPParts = glm::inverse(modelTransform) *
|
||||
glm::inverse(data.camera.combinedViewMatrix()) *
|
||||
glm::inverse(glm::dmat4(projectionTransform));
|
||||
const glm::dvec3 orthoRight = glm::normalize(
|
||||
glm::dvec3(invMVPParts * glm::dvec4(1.0, 0.0, 0.0, 0.0))
|
||||
);
|
||||
const glm::dvec3 orthoUp = glm::normalize(
|
||||
glm::dvec3(invMVPParts * glm::dvec4(0.0, 1.0, 0.0, 0.0))
|
||||
);
|
||||
|
||||
_labels->render(
|
||||
data,
|
||||
modelViewProjectionTransform,
|
||||
orthoRight,
|
||||
orthoUp,
|
||||
fadeInVariable
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderablePlanesCloud::update(const UpdateData&) {
|
||||
if (_dataIsDirty && _hasSpeckFile) {
|
||||
deleteDataGPUAndCPU();
|
||||
createPlanes();
|
||||
_dataIsDirty = false;
|
||||
}
|
||||
|
||||
if (_program->isDirty()) {
|
||||
_program->rebuildFromFile();
|
||||
ghoul::opengl::updateUniformLocations(*_program, _uniformCache, UniformNames);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderablePlanesCloud::loadTextures() {
|
||||
for (const dataloader::Dataset::Texture& tex : _dataset.textures) {
|
||||
std::filesystem::path fullPath = absPath(_texturesPath / tex.file);
|
||||
std::filesystem::path pngPath = fullPath;
|
||||
pngPath.replace_extension(".png");
|
||||
|
||||
std::filesystem::path path;
|
||||
if (std::filesystem::is_regular_file(fullPath)) {
|
||||
path = fullPath;
|
||||
}
|
||||
else if (std::filesystem::is_regular_file(pngPath)) {
|
||||
path = pngPath;
|
||||
}
|
||||
else {
|
||||
// We can't really recover from this as it would crash during rendering anyway
|
||||
throw ghoul::RuntimeError(std::format(
|
||||
"Could not find image file '{}'", tex.file
|
||||
));
|
||||
}
|
||||
|
||||
std::unique_ptr<ghoul::opengl::Texture> t =
|
||||
ghoul::io::TextureReader::ref().loadTexture(path, 2);
|
||||
|
||||
if (t) {
|
||||
LINFOC("RenderablePlanesCloud", std::format("Loaded texture '{}'", path));
|
||||
t->uploadTexture();
|
||||
t->setFilter(ghoul::opengl::Texture::FilterMode::LinearMipMap);
|
||||
t->purgeFromRAM();
|
||||
}
|
||||
else {
|
||||
// Same here, we won't be able to recover from this nullptr
|
||||
throw ghoul::RuntimeError(std::format(
|
||||
"Could not find image file '{}'", tex.file
|
||||
));
|
||||
}
|
||||
|
||||
_textureMap.insert(std::pair(tex.index, std::move(t)));
|
||||
}
|
||||
}
|
||||
|
||||
void RenderablePlanesCloud::createPlanes() {
|
||||
if (_dataIsDirty && _hasSpeckFile) {
|
||||
const int lumIdx = std::max(_dataset.index(_luminosityVar), 0);
|
||||
const double scale = toMeter(_unit);
|
||||
|
||||
LDEBUG("Creating planes...");
|
||||
float maxSize = 0.f;
|
||||
double maxRadius = 0.0;
|
||||
for (const dataloader::Dataset::Entry& e : _dataset.entries) {
|
||||
const glm::vec4 transformedPos = glm::vec4(
|
||||
_transformationMatrix * glm::dvec4(e.position, 1.0)
|
||||
);
|
||||
|
||||
const double r = glm::length(glm::dvec3(transformedPos) * scale);
|
||||
maxRadius = std::max(maxRadius, r);
|
||||
|
||||
// Plane vectors u and v
|
||||
glm::vec4 u = glm::vec4(
|
||||
_transformationMatrix *
|
||||
glm::dvec4(
|
||||
e.data[_dataset.orientationDataIndex + 0],
|
||||
e.data[_dataset.orientationDataIndex + 1],
|
||||
e.data[_dataset.orientationDataIndex + 2],
|
||||
1.f
|
||||
)
|
||||
);
|
||||
u /= 2.f;
|
||||
u.w = 0.f;
|
||||
|
||||
glm::vec4 v = glm::vec4(
|
||||
_transformationMatrix *
|
||||
glm::dvec4(
|
||||
e.data[_dataset.orientationDataIndex + 3],
|
||||
e.data[_dataset.orientationDataIndex + 4],
|
||||
e.data[_dataset.orientationDataIndex + 5],
|
||||
1.f
|
||||
)
|
||||
);
|
||||
v /= 2.f;
|
||||
v.w = 0.f;
|
||||
|
||||
if (!_luminosityVar.empty()) {
|
||||
float lumS = e.data[lumIdx] * _sluminosity;
|
||||
u *= lumS;
|
||||
v *= lumS;
|
||||
}
|
||||
|
||||
u *= _scaleFactor;
|
||||
v *= _scaleFactor;
|
||||
|
||||
glm::vec4 vertex0 = transformedPos - u - v; // same as 3
|
||||
glm::vec4 vertex1 = transformedPos + u + v; // same as 5
|
||||
glm::vec4 vertex2 = transformedPos - u + v;
|
||||
glm::vec4 vertex4 = transformedPos + u - v;
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
maxSize = std::max(maxSize, vertex0[i]);
|
||||
maxSize = std::max(maxSize, vertex1[i]);
|
||||
maxSize = std::max(maxSize, vertex2[i]);
|
||||
maxSize = std::max(maxSize, vertex4[i]);
|
||||
}
|
||||
|
||||
vertex0 = glm::vec4(glm::dvec4(vertex0) * scale);
|
||||
vertex1 = glm::vec4(glm::dvec4(vertex1) * scale);
|
||||
vertex2 = glm::vec4(glm::dvec4(vertex2) * scale);
|
||||
vertex4 = glm::vec4(glm::dvec4(vertex4) * scale);
|
||||
|
||||
const std::array<GLfloat, 36> VertexData = {
|
||||
// x y z w s t
|
||||
vertex0.x, vertex0.y, vertex0.z, 1.f, 0.f, 0.f,
|
||||
vertex1.x, vertex1.y, vertex1.z, 1.f, 1.f, 1.f,
|
||||
vertex2.x, vertex2.y, vertex2.z, 1.f, 0.f, 1.f,
|
||||
vertex0.x, vertex0.y, vertex0.z, 1.f, 0.f, 0.f,
|
||||
vertex4.x, vertex4.y, vertex4.z, 1.f, 1.f, 0.f,
|
||||
vertex1.x, vertex1.y, vertex1.z, 1.f, 1.f, 1.f,
|
||||
};
|
||||
|
||||
int textureIndex = static_cast<int>(e.data[_dataset.textureDataIndex]);
|
||||
std::unordered_map<int, PlaneAggregate>::iterator found =
|
||||
_planesMap.find(textureIndex);
|
||||
if (found != _planesMap.end()) {
|
||||
for (int i = 0; i < PlanesVertexDataSize; i++) {
|
||||
found->second.planesCoordinates.push_back(VertexData[i]);
|
||||
}
|
||||
found->second.numberOfPlanes++;
|
||||
}
|
||||
else {
|
||||
PlaneAggregate pA;
|
||||
pA.textureIndex = textureIndex;
|
||||
glGenVertexArrays(1, &pA.vao);
|
||||
glGenBuffers(1, &pA.vbo);
|
||||
pA.numberOfPlanes = 1;
|
||||
for (int i = 0; i < PlanesVertexDataSize; i++) {
|
||||
pA.planesCoordinates.push_back(VertexData[i]);
|
||||
}
|
||||
_planesMap.insert(std::pair(textureIndex, pA));
|
||||
}
|
||||
}
|
||||
|
||||
// Send data to GPU
|
||||
for (const std::pair<const int, PlaneAggregate>& pAMapItem : _planesMap) {
|
||||
glBindVertexArray(pAMapItem.second.vao);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, pAMapItem.second.vbo);
|
||||
glBufferData(
|
||||
GL_ARRAY_BUFFER,
|
||||
sizeof(GLfloat) * PlanesVertexDataSize * pAMapItem.second.numberOfPlanes,
|
||||
pAMapItem.second.planesCoordinates.data(),
|
||||
GL_STATIC_DRAW
|
||||
);
|
||||
// in_position
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), nullptr);
|
||||
|
||||
// texture coords
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(
|
||||
1,
|
||||
2,
|
||||
GL_FLOAT,
|
||||
GL_FALSE,
|
||||
6 * sizeof(GLfloat),
|
||||
reinterpret_cast<GLvoid*>(4 * sizeof(GLfloat))
|
||||
);
|
||||
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
_dataIsDirty = false;
|
||||
|
||||
setBoundingSphere(maxRadius * _scaleFactor);
|
||||
_fadeInDistances.setMaxValue(glm::vec2(10.f * maxSize));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
@@ -1,127 +0,0 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2024 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
|
||||
* software and associated documentation files (the "Software"), to deal in the Software *
|
||||
* without restriction, including without limitation the rights to use, copy, modify, *
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
|
||||
* permit persons to whom the Software is furnished to do so, subject to the following *
|
||||
* conditions: *
|
||||
* *
|
||||
* The above copyright notice and this permission notice shall be included in all copies *
|
||||
* or substantial portions of the Software. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#ifndef __OPENSPACE_MODULE_DIGITALUNIVERSE___RENDERABLEPLANESCLOUD___H__
|
||||
#define __OPENSPACE_MODULE_DIGITALUNIVERSE___RENDERABLEPLANESCLOUD___H__
|
||||
|
||||
#include <openspace/rendering/renderable.h>
|
||||
|
||||
#include <openspace/data/dataloader.h>
|
||||
#include <openspace/properties/optionproperty.h>
|
||||
#include <openspace/properties/stringproperty.h>
|
||||
#include <openspace/properties/scalar/boolproperty.h>
|
||||
#include <openspace/properties/scalar/floatproperty.h>
|
||||
#include <openspace/properties/vector/vec2property.h>
|
||||
#include <openspace/properties/vector/vec3property.h>
|
||||
#include <openspace/rendering/labelscomponent.h>
|
||||
#include <openspace/util/distanceconversion.h>
|
||||
#include <ghoul/opengl/ghoul_gl.h>
|
||||
#include <ghoul/opengl/uniformcache.h>
|
||||
#include <filesystem>
|
||||
#include <functional>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace ghoul::filesystem { class File; }
|
||||
namespace ghoul::opengl {
|
||||
class ProgramObject;
|
||||
class Texture;
|
||||
} // namespace ghoul::opengl
|
||||
|
||||
namespace openspace {
|
||||
|
||||
// (x, y, z, w, s, t) * 6 = 36
|
||||
|
||||
namespace documentation { struct Documentation; }
|
||||
|
||||
class RenderablePlanesCloud : public Renderable {
|
||||
public:
|
||||
explicit RenderablePlanesCloud(const ghoul::Dictionary& dictionary);
|
||||
~RenderablePlanesCloud() override = default;
|
||||
|
||||
void initialize() override;
|
||||
void initializeGL() override;
|
||||
void deinitializeGL() override;
|
||||
|
||||
bool isReady() const override;
|
||||
|
||||
void render(const RenderData& data, RendererTasks& rendererTask) override;
|
||||
void update(const UpdateData& data) override;
|
||||
|
||||
static documentation::Documentation Documentation();
|
||||
|
||||
private:
|
||||
struct PlaneAggregate {
|
||||
int textureIndex;
|
||||
int numberOfPlanes;
|
||||
GLuint vao;
|
||||
GLuint vbo;
|
||||
std::vector<GLfloat> planesCoordinates;
|
||||
};
|
||||
|
||||
void deleteDataGPUAndCPU();
|
||||
void createPlanes();
|
||||
void renderPlanes(const RenderData& data, const glm::dmat4& modelViewTransform,
|
||||
const glm::dmat4& projectionTransform, float fadeInVariable);
|
||||
|
||||
void loadTextures();
|
||||
|
||||
bool _hasSpeckFile = false;
|
||||
bool _dataIsDirty = true;
|
||||
bool _hasLabels = false;
|
||||
|
||||
properties::FloatProperty _scaleFactor;
|
||||
properties::BoolProperty _drawElements;
|
||||
properties::OptionProperty _blendMode;
|
||||
properties::Vec2Property _fadeInDistances;
|
||||
properties::BoolProperty _disableFadeInDistance;
|
||||
properties::FloatProperty _planeMinSize;
|
||||
properties::OptionProperty _renderOption;
|
||||
|
||||
ghoul::opengl::ProgramObject* _program = nullptr;
|
||||
UniformCache(
|
||||
modelViewProjectionTransform, alphaValue, fadeInValue, galaxyTexture
|
||||
) _uniformCache;
|
||||
std::unordered_map<int, std::unique_ptr<ghoul::opengl::Texture>> _textureMap;
|
||||
std::unordered_map<int, std::string> _textureFileMap;
|
||||
std::unordered_map<int, PlaneAggregate> _planesMap;
|
||||
|
||||
std::filesystem::path _speckFile;
|
||||
std::filesystem::path _texturesPath;
|
||||
std::string _luminosityVar;
|
||||
|
||||
DistanceUnit _unit = DistanceUnit::Parsec;
|
||||
|
||||
dataloader::Dataset _dataset;
|
||||
|
||||
// Everything related to the labels is handled by LabelsComponent
|
||||
std::unique_ptr<LabelsComponent> _labels;
|
||||
|
||||
float _sluminosity = 1.f;
|
||||
|
||||
glm::dmat4 _transformationMatrix = glm::dmat4(1.0);
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
#endif // __OPENSPACE_MODULE_DIGITALUNIVERSE___RENDERABLEPLANESCLOUD___H__
|
||||
Reference in New Issue
Block a user