KDTree refactor and some star render tweaks

Co-Authored-By: Wilhelm Björkström <143391787+Grantallkotten@users.noreply.github.com>
This commit is contained in:
Emil Wallberg
2025-03-26 16:54:29 +01:00
parent e4ff077b52
commit 724aecb3b0
4 changed files with 54 additions and 39 deletions

View File

@@ -6,7 +6,7 @@
#include <queue>
namespace {
glm::vec3 cartesianToSpherical(const glm::vec3& cartesian) {
glm::vec3 cartesianToSpherical(glm::vec3 const& cartesian) {
float radius = glm::length(cartesian);
float theta = std::atan2(glm::sqrt(cartesian.x * cartesian.x + cartesian.y * cartesian.y), cartesian.z);
float phi = std::atan2(cartesian.y, cartesian.x);
@@ -15,17 +15,25 @@ namespace {
}
}
namespace openspace {
void KDTree::build(std::string const& filePath, glm::vec3 const& origin) {
KDTree::KDTree(std::string const& filePath, glm::vec3 const& localWorldCenter, float const renderDistance) {
build(filePath, localWorldCenter, renderDistance);
}
void KDTree::build(std::string const& filePath, glm::vec3 const& localWorldCenter, float const renderDistance)
{
std::vector<Node> tree{};
const std::filesystem::path file{ absPath(filePath) };
dataloader::Dataset dataset = dataloader::data::loadFileWithCache(file);
#pragma omp parallel for
for (size_t i = 0; i < dataset.entries.size(); ++i) {
dataset.entries[i].position = cartesianToSpherical(dataset.entries[i].position - origin);
for (auto& entry : dataset.entries) {
entry.position = cartesianToSpherical(entry.position - localWorldCenter);
}
std::erase_if(dataset.entries, [renderDistance](const dataloader::Dataset::Entry& e) {
return e.position.x > renderDistance;
});
size_t numberOfStars = dataset.entries.size();
tree.resize(numberOfStars);
@@ -45,7 +53,6 @@ namespace openspace {
if (node.start >= node.end) continue;
int axis = node.depth % 2 + 1;
auto comparetor = [axis](dataloader::Dataset::Entry const& a, dataloader::Dataset::Entry const& b) -> bool {
return a.position[axis] < b.position[axis];
};
@@ -56,10 +63,9 @@ namespace openspace {
dataset.entries.begin() + node.end,
comparetor
);
size_t medianIndex{ (node.start + node.end) / 2 };
dataloader::Dataset::Entry const& entry{ dataset.entries[medianIndex] };
dataloader::Dataset::Entry const& entry{ dataset.entries[medianIndex] };
glm::vec3 const& position{ entry.position };
float const color{ entry.data[0] };
float const lum{ entry.data[1] };
@@ -68,19 +74,18 @@ namespace openspace {
if (node.index >= tree.size()) {
tree.resize(std::max(tree.size() * 2, node.index + 1));
}
tree.emplace(
tree.begin() + node.index, position, color, lum, absMag
);
// Enqueue left and right children
q.emplace(2 * node.index + 1, node.depth + 1, node.start, medianIndex);
q.emplace(2 * node.index + 2, node.depth + 1, medianIndex + 1, node.end);
}
flatTree = flattenTree(tree);
}
std::vector<float> KDTree::flatTree() const {
std::vector<float> KDTree::flattenTree(std::vector<Node> const& tree) const {
std::vector<float> flatData;
flatData.resize(tree.size() * 6);

View File

@@ -3,28 +3,37 @@
#include <glm/glm.hpp>
#include <vector>
#include <string>
#include <limits>
namespace openspace {
namespace kdtree{}
namespace kdtree {}
class KDTree {
public:
KDTree() {};
size_t size() { return tree.size() * 6; };
KDTree(std::string const& filePath, glm::vec3 const& localWorldCenter, float const renderDistance = std::numeric_limits<float>::max());
void build(std::string const& filePath, glm::vec3 const & origin);
size_t size() { return flatTree.size(); };
std::vector<float> flatTree() const;
void* data() {
return flatTree.data();
}
void build(
std::string const& constfilePath,
glm::vec3 const& localWorldCenter,
float const renderDistance = std::numeric_limits<float>::max()
);
private:
struct Node {
glm::fvec3 position;
float color;
float lum;
float absMag;
glm::fvec3 position{};
float color{};
float lum{};
float absMag{};
};
std::vector<Node> tree{};
std::vector<float> flattenTree(std::vector<Node> const& tree) const;
std::vector<float> flatTree{};
};
}

View File

@@ -113,8 +113,7 @@ namespace openspace {
void RenderableBlackHole::update(const UpdateData& data) {
if (data.modelTransform.translation != _lastTranslation) {
_starKDTree.build("${BASE}/sync/http/stars_du/6/stars.speck", data.modelTransform.translation);
flatDataStar = _starKDTree.flatTree();
_starKDTree.build("${BASE}/sync/http/stars_du/6/stars.speck", data.modelTransform.translation, 100.0f);
_lastTranslation = data.modelTransform.translation;
}
@@ -122,7 +121,7 @@ namespace openspace {
glm::vec3 cameraPosition = global::navigationHandler->camera()->positionVec3();
glm::vec3 anchorNodePosition = global::navigationHandler->anchorNode()->position();
float distanceToAnchor = (float)glm::distance(cameraPosition, anchorNodePosition) / distanceconstants::LightYear;
float distanceToAnchor = glm::distance(cameraPosition, anchorNodePosition) / static_cast<float>(distanceconstants::LightYear);
if (abs(_rCamera - distanceToAnchor) > _rs * 0.01) {
_rCamera = distanceToAnchor;
@@ -161,18 +160,20 @@ namespace openspace {
);
// Calculate the camera planes rotation to make sure fisheye works correcly (dcm in sgct projection.cpp)
glm::fmat4 invViewPlaneTranslationMatrix = glm::translate(glm::mat4(1.f), glm::vec3(renderData.camera.eyePositionVec3().x));
glm::fmat4 viewMatrix = renderData.camera.viewMatrix();
glm::fmat4 const CameraPlaneRotation = glm::inverse(viewMatrix * invViewPlaneTranslationMatrix);
glm::mat4 invViewPlaneTranslationMatrix = glm::translate(
glm::mat4(1.f), glm::vec3(static_cast<float>(renderData.camera.eyePositionVec3().x))
);
glm::mat4 viewMatrix = renderData.camera.viewMatrix();
glm::mat4 const CameraPlaneRotation = glm::inverse(viewMatrix * invViewPlaneTranslationMatrix);
_program->setUniform(
_uniformCache.cameraRotationMatrix,
glm::fmat4(glm::mat4_cast(camRot.localRotation)) * CameraPlaneRotation
glm::mat4(glm::mat4_cast(camRot.localRotation)) * CameraPlaneRotation
);
_program->setUniform(
_uniformCache.worldRotationMatrix,
glm::fmat4(glm::mat4_cast(camRot.globalRotation))
glm::mat4(glm::mat4_cast(camRot.globalRotation))
);
drawQuad();
@@ -201,12 +202,12 @@ namespace openspace {
{
glBindBuffer(GL_SHADER_STORAGE_BUFFER, _ssboStarKDTree);
const size_t indexBufferSize = flatDataStar.size() * sizeof(float);
const size_t indexBufferSize = _starKDTree.size() * sizeof(float);
glBufferData(
GL_SHADER_STORAGE_BUFFER,
indexBufferSize,
flatDataStar.data(),
_starKDTree.data(),
GL_STREAM_DRAW
);

View File

@@ -157,14 +157,13 @@ vec3 BVIndex2rgb(float color) {
return texture(colorBVMap, st).rgb;
}
const float ONE_PARSEC = 3.08567758e16; // 1 Parsec
float angularDist(vec2 a, vec2 b) {
float dTheta = a.x - b.x;
float dPhi = a.y - b.y;
return sqrt(dTheta * dTheta + sin(a.x) * sin(b.x) * dPhi * dPhi);
}
vec4 searchNearestStar(vec3 sphericalCoords) {
const int NODE_SIZE = 6;
const int SIZE = starKDTree.length() / NODE_SIZE;
@@ -172,21 +171,22 @@ vec4 searchNearestStar(vec3 sphericalCoords) {
int nodeIndex = 0;
int depth = 0;
int axis = -1;
const float starRadius = 0.0025f;
const float starRadius = 0.007f;
while(index < SIZE && starKDTree[nodeIndex] > 0.0f){
float distToStar = angularDist(sphericalCoords.yz, vec2(starKDTree[nodeIndex + 1], starKDTree[nodeIndex + 2]));
if (distToStar < starRadius){
float luminosity = pow(10.0f, 1.89f - 0.4f * starKDTree[nodeIndex + 4]);
float alpha = starRadius / distToStar;
float alpha = pow((starRadius-distToStar) / starRadius, 3.0f);
float observedDistance = starKDTree[nodeIndex];
luminosity /= pow(observedDistance, 1.2f);
luminosity /= pow(observedDistance, 1.1f);
// If luminosity is really really small then set it to a static low number.
if (luminosity < LUM_LOWER_CAP) {
luminosity = LUM_LOWER_CAP;
}
return vec4(BVIndex2rgb(starKDTree[nodeIndex + 3]), alpha) * luminosity;
return vec4(BVIndex2rgb(starKDTree[nodeIndex + 3]), alpha * luminosity);
}
@@ -199,7 +199,7 @@ vec4 searchNearestStar(vec3 sphericalCoords) {
nodeIndex = index * NODE_SIZE;
depth += 1;
}
return vec4(0.0f, 0.0f, 0.0f, 1.0f);
return vec4(0.0f);
}
@@ -252,7 +252,7 @@ Fragment getFragment() {
vec4 texColor = texture(environmentTexture, uv);
vec4 starColor = searchNearestStar(vec3(0.0f, sphericalCoords.x, sphericalCoords.y));
texColor = clamp(texColor + starColor, 0.f, 1.f);
texColor = vec4((starColor.rgb * starColor.a) + (texColor.rgb * (1-starColor.a)), 1.0f);
frag.color = texColor;
return frag;
}