made it I think faster

This commit is contained in:
yggdrasil75
2026-01-21 20:25:25 -05:00
parent 0aeed604a7
commit 5ef07c6af5
2 changed files with 136 additions and 49 deletions

View File

@@ -17,6 +17,7 @@
#include <vector> #include <vector>
#include <algorithm> #include <algorithm>
#include "../basicdefines.hpp" #include "../basicdefines.hpp"
#include <cfloat>
//constexpr char magic[4] = {'Y', 'G', 'G', '3'}; //constexpr char magic[4] = {'Y', 'G', 'G', '3'};
static constexpr int CHUNK_THRESHOLD = 16; //at this size, subdivide. static constexpr int CHUNK_THRESHOLD = 16; //at this size, subdivide.
@@ -125,6 +126,7 @@ private:
std::vector<Voxel> voxels; std::vector<Voxel> voxels;
std::unordered_map<Vec3i, Chunk, Vec3i::Hash> chunkList; std::unordered_map<Vec3i, Chunk, Vec3i::Hash> chunkList;
std::unordered_map<Vec3i, bool, Vec3i::Hash> activeChunks; std::unordered_map<Vec3i, bool, Vec3i::Hash> activeChunks;
int xyPlane;
float radians(float rads) { float radians(float rads) {
return rads * (M_PI / 180); return rads * (M_PI / 180);
@@ -143,6 +145,34 @@ private:
} }
} }
// Slab method for AABB intersection
bool intersectRayAABB(const Vec3f& origin, const Vec3f& dir, const Vec3f& boxMin, const Vec3f& boxMax, float& tNear, float& tFar) const {
Vec3f invDir(1.0f / dir.x, 1.0f / dir.y, 1.0f / dir.z);
float t1 = (boxMin.x - origin.x) * invDir.x;
float t2 = (boxMax.x - origin.x) * invDir.x;
float tMin = std::min(t1, t2);
float tMax = std::max(t1, t2);
t1 = (boxMin.y - origin.y) * invDir.y;
t2 = (boxMax.y - origin.y) * invDir.y;
tMin = std::max(tMin, std::min(t1, t2));
tMax = std::min(tMax, std::max(t1, t2));
t1 = (boxMin.z - origin.z) * invDir.z;
t2 = (boxMax.z - origin.z) * invDir.z;
tMin = std::max(tMin, std::min(t1, t2));
tMax = std::min(tMax, std::max(t1, t2));
tNear = tMin;
tFar = tMax;
return tMax >= tMin && tMax >= 0.0f;
}
public: public:
VoxelGrid() : gridSize(0,0,0) { VoxelGrid() : gridSize(0,0,0) {
std::cout << "creating empty grid." << std::endl; std::cout << "creating empty grid." << std::endl;
@@ -157,11 +187,11 @@ public:
static std::unique_ptr<VoxelGrid> deserializeFromFile(const std::string& filename); static std::unique_ptr<VoxelGrid> deserializeFromFile(const std::string& filename);
Voxel& get(int x, int y, int z) { Voxel& get(int x, int y, int z) {
return voxels[z * gridSize.x * gridSize.y + y * gridSize.x + x]; return voxels[z * xyPlane + y * gridSize.x + x];
} }
const Voxel& get(int x, int y, int z) const { const Voxel& get(int x, int y, int z) const {
return voxels[z * gridSize.x * gridSize.y + y * gridSize.x + x]; return voxels[z * xyPlane + y * gridSize.x + x];
} }
Voxel& get(const Vec3i& xyz) { Voxel& get(const Vec3i& xyz) {
@@ -203,6 +233,7 @@ public:
voxels = std::move(newVoxels); voxels = std::move(newVoxels);
activeChunks = std::move(newActiveChunks); activeChunks = std::move(newActiveChunks);
gridSize = Vec3i(newW, newH, newD); gridSize = Vec3i(newW, newH, newD);
xyPlane = gridSize.x * gridSize.y;
} }
void resize(Vec3i newsize) { void resize(Vec3i newsize) {
@@ -252,38 +283,18 @@ public:
return voxl.AllGTE(0) && voxl.AllLT(gridSize); return voxl.AllGTE(0) && voxl.AllLT(gridSize);
} }
void voxelTraverse(const Vec3f& origin, const Vec3f& end, Voxel& outVoxel, int maxDist = 10000000) const { void voxelTraverse(const Vec3f& origin, const Vec3f& end, Voxel& outVoxel, Vec3i& step, const Vec3f& ray, Vec3f& tMax, int maxDist = 10000000) const {
Vec3i cv = origin.floorToI(); Vec3i cv = origin.floorToI();
Vec3i lv = end.floorToI(); Vec3i lv = end.floorToI();
Vec3f ray = end - origin; step = Vec3i(ray.x >= 0 ? 1 : -1, ray.y >= 0 ? 1 : -1, ray.z >= 0 ? 1 : -1);
Vec3i step = end.mask([](float v, float zero) { return v >= zero; }, 0.0f) * 2 - Vec3i(1);
Vec3f tDelta = Vec3f(ray.x != 0 ? std::abs(1.0f / ray.x) : INF, Vec3f tDelta = Vec3f(ray.x != 0 ? std::abs(1.0f / ray.x) : INF,
ray.y != 0 ? std::abs(1.0f / ray.y) : INF, ray.y != 0 ? std::abs(1.0f / ray.y) : INF,
ray.z != 0 ? std::abs(1.0f / ray.z) : INF); ray.z != 0 ? std::abs(1.0f / ray.z) : INF);
Vec3f tMax;
if (ray.x > 0) {
tMax.x = (std::floor(origin.x) + 1.0f - origin.x) / ray.x;
} else if (ray.x < 0) {
tMax.x = (origin.x - std::floor(origin.x)) / -ray.x;
} else tMax.x = INF;
if (ray.y > 0) {
tMax.y = (std::floor(origin.y) + 1.0f - origin.y) / ray.y;
} else if (ray.y < 0) {
tMax.y = (origin.y - std::floor(origin.y)) / -ray.y;
} else tMax.y = INF;
if (ray.z > 0) {
tMax.z = (std::floor(origin.z) + 1.0f - origin.z) / ray.z;
} else if (ray.z < 0) {
tMax.z = (origin.z - std::floor(origin.z)) / -ray.z;
} else tMax.z = INF;
float dist = 0.0f; float dist = 0.0f;
outVoxel.alpha = 0.0; outVoxel.alpha = 0.0;
while (lv != cv && dist < 1.f && inGrid(cv) && outVoxel.alpha < 1.f) { while (lv != cv && inGrid(cv) && outVoxel.alpha < 1.f) {
const Voxel& curv = get(cv); const Voxel& curv = get(cv);
if (curv.active) { if (curv.active) {
@@ -300,27 +311,24 @@ public:
} }
// Step Logic // Step Logic
if (tMax.x < tMax.y) { int axis = (tMax.x < tMax.y) ?
if (tMax.x < tMax.z) { ((tMax.x < tMax.z) ? 0 : 2) :
dist = tMax.x; ((tMax.y < tMax.z) ? 1 : 2);
cv.x += step.x;
tMax.x += tDelta.x; switch(axis) {
} else { case 0:
dist = tMax.z; tMax.x += tDelta.x;
cv.z += step.z; cv.x += step.x;
tMax.z += tDelta.z; break;
case 1:
tMax.y += tDelta.y;
cv.y += step.y;
break;
case 2:
tMax.z += tDelta.z;
cv.z += step.z;
break;
} }
} else {
if (tMax.y < tMax.z) {
dist = tMax.y;
cv.y += step.y;
tMax.y += tDelta.y;
} else {
dist = tMax.z;
cv.z += step.z;
tMax.z += tDelta.z;
}
}
} }
//outVoxel.color = newC //outVoxel.color = newC
return; return;
@@ -343,11 +351,41 @@ public:
Vec3f up = cam.up; Vec3f up = cam.up;
float aspect = resolution.aspect(); float aspect = resolution.aspect();
float fovRad = cam.fovRad();
float viewH = tan(cam.fov * 0.5f); float viewH = tan(cam.fov * 0.5f);
float viewW = viewH * aspect; float viewW = viewH * aspect;
float maxDist = std::sqrt(gridSize.lengthSquared()); float maxDist = std::sqrt(gridSize.lengthSquared());
Vec3i step;
// Defines the bounds of the grid for AABB checking
Vec3f gridMin(0, 0, 0);
std::array<Vec3i, 8> precomputedSteps;
int baseQuadrant = 0;
baseQuadrant = forward.calculateInvOctantMask();
precomputedSteps[0] = Vec3i(1, 1, 1); // +++
precomputedSteps[1] = Vec3i(-1, 1, 1); // -++
precomputedSteps[2] = Vec3i(1, -1, 1); // +-+
precomputedSteps[3] = Vec3i(-1, -1, 1); // --+
precomputedSteps[4] = Vec3i(1, 1, -1); // ++-
precomputedSteps[5] = Vec3i(-1, 1, -1); // -+-
precomputedSteps[6] = Vec3i(1, -1, -1); // +--
precomputedSteps[7] = Vec3i(-1, -1, -1);// ---
std::array<Vec3f, 8> precomputedTMax;
Vec3f floored = cam.posfor.origin.floor();
Vec3f dNext = floored + 1.f - cam.posfor.origin;
Vec3f dPrev = cam.posfor.origin - floored;
precomputedTMax[0] = Vec3f(dNext.x, dNext.y, dNext.z);
precomputedTMax[1] = Vec3f(dPrev.x, dNext.y, dNext.z);
precomputedTMax[2] = Vec3f(dNext.x, dPrev.y, dNext.z);
precomputedTMax[3] = Vec3f(dPrev.x, dPrev.y, dNext.z);
precomputedTMax[4] = Vec3f(dNext.x, dNext.y, dPrev.z);
precomputedTMax[5] = Vec3f(dPrev.x, dNext.y, dPrev.z);
precomputedTMax[6] = Vec3f(dNext.x, dPrev.y, dPrev.z);
precomputedTMax[7] = Vec3f(dPrev.x, dPrev.y, dPrev.z);
frame outFrame(resolution.x, resolution.y, colorformat); frame outFrame(resolution.x, resolution.y, colorformat);
std::vector<uint8_t> colorBuffer; std::vector<uint8_t> colorBuffer;
if (colorformat == frame::colormap::RGB) { if (colorformat == frame::colormap::RGB) {
@@ -360,13 +398,54 @@ public:
for (int y = 0; y < resolution.y; y++) { for (int y = 0; y < resolution.y; y++) {
float v = (1.f - 2.f * (y+0.5f) / resolution.y) * viewH; float v = (1.f - 2.f * (y+0.5f) / resolution.y) * viewH;
Vec3f vup = up * v; Vec3f vup = up * v;
int yQuad = baseQuadrant;
if (v < 0) yQuad ^= 2;
for (int x = 0; x < resolution.x; x++) { for (int x = 0; x < resolution.x; x++) {
Voxel outVoxel(0, false, 0.f, Vec3ui8(10, 10, 255)); Voxel outVoxel(0, false, 0.f, Vec3ui8(10, 10, 255));
float u = (2.f * (x+0.5f)/resolution.x - 1.f) * viewW; float u = (2.f * (x+0.5f)/resolution.x - 1.f) * viewW;
Vec3f rayDirWorld = (forward + right * u + vup).normalized(); Vec3f rayDirWorld = (forward + right * u + vup).normalized();
Vec3f rayStartGrid = cam.posfor.origin; float tNear = 0.0f;
Vec3f rayEnd = rayStartGrid + rayDirWorld * maxDist; float tFar = maxDist;
voxelTraverse(rayStartGrid, rayEnd, outVoxel, maxDist); bool hit = intersectRayAABB(cam.posfor.origin, rayDirWorld, gridMin, gridSize, tNear, tFar);
if (!hit) {
Vec3ui8 hitColor = outVoxel.color;
// Set pixel color in buffer
switch (colorformat) {
case frame::colormap::BGRA: {
int idx = (y * resolution.y + x) * 4;
colorBuffer[idx + 3] = hitColor.x;
colorBuffer[idx + 2] = hitColor.y;
colorBuffer[idx + 1] = hitColor.z;
colorBuffer[idx + 0] = 255;
break;
}
case frame::colormap::RGB:
default: {
int idx = (y * resolution.y + x) * 3;
colorBuffer[idx] = hitColor.x;
colorBuffer[idx + 1] = hitColor.y;
colorBuffer[idx + 2] = hitColor.z;
break;
}
}
continue;
}
Vec3f rayStartGrid = cam.posfor.origin; // + rayDirWorld * tNear;
Vec3f rayEnd = rayStartGrid + rayDirWorld * tFar;
int xQuad = yQuad;
if (u < 0) xQuad ^= 1;
step = precomputedSteps[xQuad];
Vec3f tMaxBase = precomputedTMax[xQuad];
Vec3f ray = rayEnd - rayStartGrid;
Vec3f tMax(
ray.x != 0 ? tMaxBase.x / std::abs(ray.x) : INF,
ray.y != 0 ? tMaxBase.y / std::abs(ray.y) : INF,
ray.z != 0 ? tMaxBase.z / std::abs(ray.z) : INF
);
voxelTraverse(rayStartGrid, rayEnd, outVoxel, step, ray, tMax, maxDist);
Vec3ui8 hitColor = outVoxel.color; Vec3ui8 hitColor = outVoxel.color;
// Set pixel color in buffer // Set pixel color in buffer
switch (colorformat) { switch (colorformat) {

View File

@@ -495,6 +495,14 @@ public:
if (z > 0.f) mask |= 4; if (z > 0.f) mask |= 4;
return mask; return mask;
} }
uint8_t calculateInvOctantMask() const {
uint8_t mask = 0;
if (x < 0.f) mask |= 1;
if (y < 0.f) mask |= 2;
if (z < 0.f) mask |= 4;
return mask;
}
T maxComp() const { T maxComp() const {
return std::max({x, y, z}); return std::max({x, y, z});