[WIP] Velocity works but something's off with the units

This commit is contained in:
Jacob Molin
2022-06-10 16:51:13 -06:00
parent d341961c40
commit 170ef5639e
10 changed files with 302 additions and 19 deletions

View File

@@ -42,15 +42,17 @@
#include <ghoul/opengl/textureunit.h>
#include <fstream>
int TIME_COUNTER = 0;
namespace {
constexpr const char* _loggerCat = "PointsCloud";
constexpr const std::array<const char*, 18> UniformNames = {
constexpr const std::array<const char*, 20> UniformNames = {
"color", "opacity", "size", "modelMatrix", "cameraUp", "screenSize",
"cameraViewProjectionMatrix", "eyePosition", "sizeOption",
"colormapTexture", "colormapMin", "colormapMax", "cmapNaNMode",
"cmapNaNColor", "colormapEnabled", "linearSizeMin", "linearSizeMax",
"linearSizeEnabled"
"linearSizeEnabled", "motionEnabled", "theTime"
};
constexpr openspace::properties::Property::PropertyInfo ColorInfo = {
@@ -131,6 +133,12 @@ namespace {
"Boolean to determine whether to use linear size or not."
};
constexpr openspace::properties::Property::PropertyInfo MotionEnabledInfo = {
"MotionEnabled",
"Motion enabled",
"Boolean to determine whether to use motion or not."
};
struct [[codegen::Dictionary(RenderablePointsCloud)]] Parameters {
// [[codegen::verbatim(ColorInfo.description)]]
std::optional<glm::vec4> color;
@@ -138,6 +146,7 @@ namespace {
// [[codegen::verbatim(SizeInfo.description)]]
std::optional<float> size;
// TODO: This can be removed? Not in use anymore?
// [[codegen::verbatim(DataInfo.description)]]
std::optional<std::vector<glm::vec3>> data;
@@ -168,6 +177,9 @@ namespace {
// [[codegen::verbatim(LinearSizeEnabledInfo.description)]]
std::optional<bool> linearSizeEnabled;
// [[codegen::verbatim(MotionEnabledInfo.description)]]
std::optional<bool> motionEnabled;
enum class SizeOption : uint32_t {
Uniform,
NonUniform
@@ -198,7 +210,8 @@ RenderablePointsCloud::RenderablePointsCloud(const ghoul::Dictionary& dictionary
, _colormapEnabled(ColormapEnabledInfo, false)
, _linearSizeMax(LinearSizeMinInfo)
, _linearSizeMin(LinearSizeMaxInfo)
, _linearSizeEnabled(LinearSizeEnabledInfo)
, _linearSizeEnabled(LinearSizeEnabledInfo, false)
, _motionEnabled(MotionEnabledInfo, false)
{
const Parameters p = codegen::bake<Parameters>(dictionary);
@@ -275,6 +288,10 @@ RenderablePointsCloud::RenderablePointsCloud(const ghoul::Dictionary& dictionary
_linearSizeMax.setVisibility(properties::Property::Visibility::Hidden);
_linearSizeMax.onChange(linearSizeMinMaxChecker);
addProperty(_linearSizeMax);
_motionEnabled = p.motionEnabled.value_or(_motionEnabled);
_motionEnabled.onChange([this] { checkIfMotionCanBeEnabled(); });
addProperty(_motionEnabled);
}
bool RenderablePointsCloud::isReady() const {
@@ -367,6 +384,12 @@ void RenderablePointsCloud::render(const RenderData& data, RendererTasks&) {
_shaderProgram->setUniform(_uniformCache.linearSizeMax, _linearSizeMax);
_shaderProgram->setUniform(_uniformCache.linearSizeEnabled, _linearSizeEnabled);
_shaderProgram->setUniform(_uniformCache.motionEnabled, _motionEnabled);
_shaderProgram->setUniform(
_uniformCache.theTime,
static_cast<float>(data.time.j2000Seconds())
);
_shaderProgram->setUniform(_uniformCache.color, _color);
_shaderProgram->setUniform(_uniformCache.opacity, _opacity);
@@ -415,6 +438,7 @@ void RenderablePointsCloud::update(const UpdateData&) {
auto pointDataSlice = getDataSlice(DataSliceKey::Points);
auto colormapAttrDataSlice = getDataSlice(DataSliceKey::ColormapAttributes);
auto linearSizeAttrDataSlice = getDataSlice(DataSliceKey::LinearSizeAttributes);
auto velocityDataSlice = getDataSlice(DataSliceKey::Velocity);
if (pointDataSlice->empty()) return;
@@ -431,14 +455,28 @@ void RenderablePointsCloud::update(const UpdateData&) {
bufferData.push_back(colormapAttrDataSlice->at(i));
}
else {
bufferData.push_back(0.0);
bufferData.push_back(0.0); // TODO: We might not want to put 0.0 here. How is this rendered?
}
if (linearSizeAttrDataSlice->size() > i) {
bufferData.push_back(linearSizeAttrDataSlice->at(i));
}
else {
bufferData.push_back(0.0);
bufferData.push_back(0.0); // TODO: We might not want to put 0.0 here. How is this rendered?
}
if (velocityDataSlice->size() > (j + 2)) {
bufferData.push_back(velocityDataSlice->at(j));
bufferData.push_back(velocityDataSlice->at(j + 1));
bufferData.push_back(velocityDataSlice->at(j + 2));
}
else {
bufferData.push_back(std::nan("0")); // TODO: We might not want to put 0.0 here. How is this rendered? Maybe push NAN?
bufferData.push_back(std::nan("0")); // TODO: We might not want to put 0.0 here. How is this rendered? Maybe push NAN?
bufferData.push_back(std::nan("0")); // TODO: We might not want to put 0.0 here. How is this rendered? Maybe push NAN?
// bufferData.push_back(0.0); // TODO: We might not want to put 0.0 here. How is this rendered? Maybe push NAN?
// bufferData.push_back(0.0); // TODO: We might not want to put 0.0 here. How is this rendered? Maybe push NAN?
// bufferData.push_back(0.0); // TODO: We might not want to put 0.0 here. How is this rendered? Maybe push NAN?
}
}
@@ -451,7 +489,7 @@ void RenderablePointsCloud::update(const UpdateData&) {
// ==============================================================================================
// ========================================= VAO stuff =========================================
GLsizei stride = static_cast<GLsizei>(sizeof(GLfloat) * 5);
GLsizei stride = static_cast<GLsizei>(sizeof(GLfloat) * _nValuesForVAOStride);
GLint positionAttribute = _shaderProgram->attributeLocation("in_position");
glEnableVertexAttribArray(positionAttribute);
glVertexAttribPointer(
@@ -488,6 +526,19 @@ void RenderablePointsCloud::update(const UpdateData&) {
reinterpret_cast<void*>(sizeof(GLfloat) * 4)
);
}
if (_hasLoadedVelocityData) {
GLint velocityAttribute = _shaderProgram->attributeLocation("in_velocity");
glEnableVertexAttribArray(velocityAttribute);
glVertexAttribPointer(
velocityAttribute,
3,
GL_FLOAT,
GL_FALSE,
stride,
reinterpret_cast<void*>(sizeof(GLfloat) * 5)
);
}
// ==============================================================================================
glBindBuffer(GL_ARRAY_BUFFER, 0);
@@ -522,6 +573,11 @@ bool RenderablePointsCloud::checkDataStorage() {
loadLinearSizeAttributeData(softwareIntegrationModule);
updatedDataSlices = true;
}
if (softwareIntegrationModule->isDataDirty(_identifier.value(), storage::Key::VelocityData)) {
loadVelocityData(softwareIntegrationModule);
updatedDataSlices = true;
}
return updatedDataSlices;
}
@@ -537,7 +593,7 @@ void RenderablePointsCloud::loadData(SoftwareIntegrationModule* softwareIntegrat
auto pointDataSlice = getDataSlice(DataSliceKey::Points);
pointDataSlice->clear();
pointDataSlice->reserve(fullPointData.size() * 3);
pointDataSlice->reserve(fullPointData.size() * 3); // TODO: Do we really need *3 here?
// Create data slice
auto addPosition = [&](const glm::vec4& pos) {
@@ -616,7 +672,7 @@ void RenderablePointsCloud::loadCmapAttributeData(SoftwareIntegrationModule* sof
}
_hasLoadedColormapAttributeData = true;
LDEBUG("Rerendering colormap attribute data");
LDEBUG("Rerendering with colormap attribute data");
}
void RenderablePointsCloud::loadLinearSizeAttributeData(SoftwareIntegrationModule* softwareIntegrationModule) {
@@ -634,7 +690,7 @@ void RenderablePointsCloud::loadLinearSizeAttributeData(SoftwareIntegrationModul
"There is a mismatch in the amount of linear size attribute scalars ({}) and the amount of points ({})",
linearSizeAttributeData.size(), pointDataSlice->size() / 3
));
_colormapEnabled = false;
_linearSizeEnabled = false;
return;
}
@@ -647,9 +703,108 @@ void RenderablePointsCloud::loadLinearSizeAttributeData(SoftwareIntegrationModul
}
_hasLoadedLinearSizeAttributeData = true;
LDEBUG("Rerendering linear size attribute data");
LDEBUG("Rerendering with linear size attribute data");
}
void RenderablePointsCloud::loadVelocityData(SoftwareIntegrationModule* softwareIntegrationModule) {
// Fetch data from module's centralized storage
auto velocityData = softwareIntegrationModule->fetchData(_identifier.value(), storage::Key::VelocityData);
if (velocityData.empty()) {
LWARNING("There was an issue trying to fetch the velocity data from the centralized storage.");
return;
}
auto pointDataSlice = getDataSlice(DataSliceKey::Points);
if (pointDataSlice->size() != velocityData.size()) {
LWARNING(fmt::format(
"There is a mismatch in the amount of velocity data ({}) and the amount of points ({})",
velocityData.size() / 3, pointDataSlice->size() / 3
));
_motionEnabled = false;
return;
}
auto velocityDataSlice = getDataSlice(DataSliceKey::Velocity);
velocityDataSlice->clear();
velocityDataSlice->reserve(velocityData.size() * 3); // TODO: Do we really need *3 here?
// =========================================
int nNans = 0;
int prevNNans = 0;
int nPointsContainingNans = 0;
// Create velocity data slice
auto addPosition = [&](const glm::vec4& pos) {
for (glm::vec4::length_type j = 0; j < glm::vec4::length() - 1; ++j) {
if (isnan(pos[j])) {
nNans++;
}
velocityDataSlice->push_back(pos[j]);
}
if (prevNNans < nNans) {
nPointsContainingNans++;
prevNNans = nNans;
}
};
for (size_t i = 0; i < velocityData.size(); i += 3) {
glm::dvec4 transformedPos = {
velocityData[i + 0],
velocityData[i + 1],
velocityData[i + 2],
1.0
};
// W-normalization
transformedPos /= transformedPos.w;
transformedPos *= distanceconstants::Parsec; // TODO: Is this converting parsec => meter?
addPosition(transformedPos);
}
LWARNING(fmt::format("Points: {}. Velocity points: {}. Velocity points w/ nans {}. Velocity nans in total: {}", pointDataSlice->size()/3, velocityData.size()/3, nPointsContainingNans, nNans));
// =========================================
_hasLoadedVelocityData = true;
LDEBUG("Rerendering with motion based on velocity data");
}
// void RenderablePointsCloud::loadData(SoftwareIntegrationModule* softwareIntegrationModule) {
// // Fetch data from module's centralized storage
// auto fullPointData = softwareIntegrationModule->fetchData(_identifier.value(), storage::Key::DataPoints);
// if (fullPointData.empty()) {
// LWARNING("There was an issue trying to fetch the point data from the centralized storage.");
// return;
// }
// auto pointDataSlice = getDataSlice(DataSliceKey::Points);
// pointDataSlice->clear();
// pointDataSlice->reserve(fullPointData.size() * 3);
// // Create data slice
// auto addPosition = [&](const glm::vec4& pos) {
// for (glm::vec4::length_type j = 0; j < glm::vec4::length() - 1; ++j) {
// pointDataSlice->push_back(pos[j]);
// }
// };
// for (size_t i = 0; i < fullPointData.size(); i += 3) {
// glm::dvec4 transformedPos = {
// fullPointData[i + 0],
// fullPointData[i + 1],
// fullPointData[i + 2],
// 1.0
// };
// // W-normalization
// transformedPos /= transformedPos.w;
// transformedPos *= distanceconstants::Parsec;
// addPosition(transformedPos);
// }
// }
std::shared_ptr<RenderablePointsCloud::DataSlice> RenderablePointsCloud::getDataSlice(DataSliceKey key) {
if (!_dataSlices.count(key)) {
_dataSlices.insert({ key, std::make_shared<DataSlice>() });
@@ -699,6 +854,24 @@ void RenderablePointsCloud::checkIfLinearSizeCanBeEnabled() {
}
}
void RenderablePointsCloud::checkIfMotionCanBeEnabled() {
if (!global::windowDelegate->isMaster()) return;
// This can happen if the user checks the "MotionEnabled" checkbox in the GUI
auto velocityData = getDataSlice(DataSliceKey::Velocity);
if (_motionEnabled.value() && velocityData->empty()) {
LINFO("Velocity data not loaded. Has it been sent from external software?");
global::scriptEngine->queueScript(
fmt::format(
"openspace.setPropertyValueSingle('Scene.{}.Renderable.MotionEnabled', {});",
_identifier.value(), "false"
),
scripting::ScriptEngine::RemoteScripting::Yes
);
}
LINFO(fmt::format("checkIfMotionCanBeEnabled(): MotionEnabled = {}", _motionEnabled));
}
void RenderablePointsCloud::checkColormapMinMax() {
float min = std::any_cast<float>(_colormapMin.get());
float max = std::any_cast<float>(_colormapMax.get());