lets try speeding it up again.
This commit is contained in:
@@ -26,6 +26,12 @@ struct defaults {
|
||||
int outWidth = 512;
|
||||
int outHeight = 512;
|
||||
int gridSizecube = 10000;
|
||||
bool slowRender = false;
|
||||
bool globalIllumination = true;
|
||||
int rayCount = 3;
|
||||
int reflectCount = 3;
|
||||
int lodDist;
|
||||
float lodDropoff;
|
||||
PNoise2 noise = PNoise2(42);
|
||||
};
|
||||
|
||||
@@ -399,9 +405,15 @@ void livePreview(Octree<int>& grid, defaults& config, const Camera& cam) {
|
||||
updatePreview = true;
|
||||
|
||||
auto renderStart = std::chrono::high_resolution_clock::now();
|
||||
frame currentPreviewFrame;
|
||||
grid.setLODMinDistance(config.lodDist);
|
||||
grid.setLODFalloff(config.lodDropoff);
|
||||
if (config.slowRender) {
|
||||
currentPreviewFrame = grid.renderFrame(cam, config.outWidth, config.outHeight, frame::colormap::RGB, config.rayCount, config.reflectCount, config.globalIllumination);
|
||||
} else {
|
||||
currentPreviewFrame = grid.fastRenderFrame(cam, config.outWidth, config.outHeight, frame::colormap::RGB);
|
||||
}
|
||||
|
||||
frame currentPreviewFrame = grid.fastRenderFrame(cam, config.outWidth, config.outHeight, frame::colormap::RGB);
|
||||
//frame currentPreviewFrame = grid.renderFrame(cam, config.outWidth, config.outHeight, frame::colormap::RGB, 3, 2, true);
|
||||
|
||||
auto renderEnd = std::chrono::high_resolution_clock::now();
|
||||
renderFrameTime = std::chrono::duration<double>(renderEnd - renderStart).count();
|
||||
@@ -649,7 +661,7 @@ int main() {
|
||||
ImGui::NewFrame();
|
||||
|
||||
{
|
||||
ImGui::Begin("Controls");
|
||||
ImGui::Begin("Sim Controls");
|
||||
|
||||
ImGui::Text("Planet");
|
||||
float pos[3] = { sphereConf.centerX, sphereConf.centerY, sphereConf.centerZ };
|
||||
@@ -711,7 +723,6 @@ int main() {
|
||||
|
||||
{
|
||||
ImGui::Begin("Planet Preview");
|
||||
ImGui::Checkbox("update Preview", &worldPreview);
|
||||
if (worldPreview) {
|
||||
if (gridInitialized) {
|
||||
livePreview(grid, config, cam);
|
||||
@@ -913,6 +924,18 @@ int main() {
|
||||
ImGui::SliderFloat("Pitch Speed", &pitchSpeed, 0.0f, 2.0f, "%.2f deg/sec");
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
ImGui::Checkbox("update Preview", &worldPreview);
|
||||
ImGui::Checkbox("Use Slower renderer", &config.slowRender);
|
||||
if (config.slowRender) {
|
||||
ImGui::InputInt("Rays per pixel", &config.rayCount);
|
||||
ImGui::InputInt("Max reflections", &config.reflectCount);
|
||||
}
|
||||
ImGui::InputFloat("Lod dropoff", &config.lodDropoff);
|
||||
ImGui::InputInt("lod minimum Distance", &config.lodDist);
|
||||
ImGui::Checkbox("use Global illumination", &config.globalIllumination);
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
|
||||
@@ -75,6 +75,7 @@ public:
|
||||
std::vector<std::shared_ptr<NodeData>> points;
|
||||
std::array<std::unique_ptr<OctreeNode>, 8> children;
|
||||
PointType center;
|
||||
float nodeSize;
|
||||
bool isLeaf;
|
||||
|
||||
mutable std::shared_ptr<NodeData> lodData;
|
||||
@@ -85,6 +86,7 @@ public:
|
||||
child = nullptr;
|
||||
}
|
||||
center = (bounds.first + bounds.second) * 0.5;
|
||||
nodeSize = (bounds.second - bounds.first).norm();
|
||||
}
|
||||
|
||||
bool contains(const PointType& point) const {
|
||||
@@ -504,6 +506,24 @@ private:
|
||||
return 0.2126f * color[0] + 0.7152f * color[1] + 0.0722f * color[2];
|
||||
}
|
||||
|
||||
void collectNodesByObjectId(OctreeNode* node, int id, std::vector<std::shared_ptr<NodeData>>& results) const {
|
||||
if (!node) return;
|
||||
|
||||
if (node->isLeaf) {
|
||||
for (const auto& pt : node->points) {
|
||||
if (pt->active && (id == -1 || pt->objectId == id)) {
|
||||
results.push_back(pt);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (const auto& child : node->children) {
|
||||
if (child) {
|
||||
collectNodesByObjectId(child.get(), id, results);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
Octree(const PointType& minBound, const PointType& maxBound, size_t maxPointsPerNode=16, size_t maxDepth = 16) :
|
||||
root_(std::make_unique<OctreeNode>(minBound, maxBound)), maxPointsPerNode(maxPointsPerNode),
|
||||
@@ -847,55 +867,47 @@ public:
|
||||
std::vector<std::shared_ptr<NodeData>> hits;
|
||||
|
||||
if (empty()) return hits;
|
||||
float invLodf = 1.0f / lodFalloffRate_;
|
||||
uint8_t raySignMask = (direction.x() < 0 ? 1 : 0) | (direction.y() < 0 ? 2 : 0) | (direction.z() < 0 ? 4 : 0);
|
||||
|
||||
std::function<void(OctreeNode*, const PointType&, const PointType&, float, float)> traverseNode =
|
||||
[&](OctreeNode* node, const PointType& origin, const PointType& dir, float tMin, float tMax) {
|
||||
if (!node || tMin > tMax) return;
|
||||
if (!node) return;
|
||||
|
||||
if (enableLOD && !node->isLeaf) {
|
||||
float dist = (node->center - origin).norm();
|
||||
float nodeSize = (node->bounds.second - node->bounds.first).norm();
|
||||
// if (enableLOD && !node->isLeaf) {
|
||||
// float dist = (node->center - origin).norm();
|
||||
|
||||
if (dist > lodMinDistance_) {
|
||||
float ratio = dist / (nodeSize + 0.0001f);
|
||||
// if (dist > lodMinDistance_) {
|
||||
// float ratio = dist / (node->nodeSize + 0.0001f);
|
||||
|
||||
if (ratio > (1.0f / lodFalloffRate_)) {
|
||||
ensureLOD(node);
|
||||
if (node->lodData) {
|
||||
if (node->lodData->shape == Shape::SPHERE) {
|
||||
float t;
|
||||
if (raySphereIntersect(origin, dir, node->lodData->position, node->lodData->size, t)) {
|
||||
if (t >= 0 && t <= maxDist) hits.emplace_back(node->lodData);
|
||||
}
|
||||
} else {
|
||||
float t; PointType n, h;
|
||||
if (rayCubeIntersect(origin, dir, node->lodData.get(), t, n, h)) {
|
||||
if (t >= 0 && t <= maxDist) hits.emplace_back(node->lodData);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// if (ratio > (invLodf)) {
|
||||
// ensureLOD(node);
|
||||
// if (node->lodData) {
|
||||
// float t;
|
||||
// PointType n;
|
||||
// PointType h;
|
||||
// if (rayCubeIntersect(origin, dir, node->lodData.get(), t, n, h)) {
|
||||
// if (t >= 0 && t <= maxDist) hits.emplace_back(node->lodData);
|
||||
// }
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
if (node->isLeaf) {
|
||||
for (const auto& pointData : node->points) {
|
||||
if (!pointData->active) continue;
|
||||
|
||||
if (pointData->shape == Shape::SPHERE) {
|
||||
PointType center = pointData->position;
|
||||
float radius = pointData->size;
|
||||
float t;
|
||||
|
||||
if (raySphereIntersect(origin, dir, center, radius, t)) {
|
||||
if (t >= 0 && t <= maxDist) {
|
||||
hits.emplace_back(pointData);
|
||||
if (stopAtFirstHit) return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
float t;
|
||||
// if (pointData->shape == Shape::SPHERE) {
|
||||
// if (raySphereIntersect(origin, dir, pointData->position, pointData->size, t)) {
|
||||
// if (t >= 0 && t <= maxDist) {
|
||||
// hits.emplace_back(pointData);
|
||||
// if (stopAtFirstHit) return;
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
PointType normal, hitPoint;
|
||||
if (rayCubeIntersect(origin, dir, pointData.get(), t, normal, hitPoint)) {
|
||||
if (t >= 0 && t <= maxDist) {
|
||||
@@ -903,25 +915,12 @@ public:
|
||||
if (stopAtFirstHit) return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// }
|
||||
}
|
||||
} else {
|
||||
std::array<std::pair<int, float>, 8> childOrder;
|
||||
PointType center = node->center;
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
if (node->children[i]) {
|
||||
PointType childCenter = node->children[i]->center;
|
||||
float dist = (childCenter - origin).dot(dir);
|
||||
childOrder[i] = {i, dist};
|
||||
} else {
|
||||
childOrder[i] = {i, std::numeric_limits<float>::lowest()};
|
||||
}
|
||||
}
|
||||
int childIdx = i ^ raySignMask;
|
||||
|
||||
bitonic_sort_8(childOrder);
|
||||
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
int childIdx = childOrder[i].first;
|
||||
if (node->children[childIdx]) {
|
||||
const auto& childBounds = node->children[childIdx]->bounds;
|
||||
|
||||
@@ -938,10 +937,8 @@ public:
|
||||
float tMin, tMax;
|
||||
if (rayBoxIntersect(origin, direction, root_->bounds, tMin, tMax)) {
|
||||
tMax = std::min(tMax, maxDist);
|
||||
if (tMin <= tMax) {
|
||||
traverseNode(root_.get(), origin, direction, tMin, tMax);
|
||||
}
|
||||
}
|
||||
return hits;
|
||||
}
|
||||
|
||||
@@ -1299,6 +1296,44 @@ public:
|
||||
return outFrame;
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<NodeData>> getExternalNodes(int targetObjectId) {
|
||||
std::vector<std::shared_ptr<NodeData>> candidates;
|
||||
std::vector<std::shared_ptr<NodeData>> surfaceNodes;
|
||||
|
||||
collectNodesByObjectId(root_.get(), targetObjectId, candidates);
|
||||
|
||||
if (candidates.empty()) return surfaceNodes;
|
||||
|
||||
surfaceNodes.reserve(candidates.size());
|
||||
|
||||
const std::array<PointType, 6> directions = {
|
||||
PointType(1, 0, 0), PointType(-1, 0, 0), PointType(0, 1, 0),
|
||||
PointType(0, -1, 0), PointType(0, 0, 1), PointType(0, 0, -1)
|
||||
};
|
||||
|
||||
for (const auto& node : candidates) {
|
||||
bool isExposed = false;
|
||||
float step = node->size;
|
||||
for (const auto& dir : directions) {
|
||||
PointType probePos = node->position + (dir * step);
|
||||
auto neighbor = find(probePos, step * 0.25f);
|
||||
|
||||
if (neighbor == nullptr || !neighbor->active || neighbor->objectId != node->objectId) {
|
||||
isExposed = true;
|
||||
}
|
||||
|
||||
if (isExposed) break;
|
||||
}
|
||||
|
||||
if (isExposed) {
|
||||
surfaceNodes.push_back(node);
|
||||
}
|
||||
}
|
||||
surfaceNodes.shrink_to_fit();
|
||||
|
||||
return surfaceNodes;
|
||||
}
|
||||
|
||||
void printStats(std::ostream& os = std::cout) const {
|
||||
if (!root_) {
|
||||
os << "[Octree Stats] Tree is null/empty." << std::endl;
|
||||
|
||||
Reference in New Issue
Block a user