pushing some stuff home
This commit is contained in:
@@ -29,7 +29,10 @@ class VoxelGrid {
|
||||
private:
|
||||
size_t width, height, depth;
|
||||
std::vector<Voxel> voxels;
|
||||
|
||||
float radians(float rads) {
|
||||
return rads * (M_PI / 180);
|
||||
}
|
||||
|
||||
static Mat4f lookAt(Vec3f const& eye, Vec3f const& center, Vec3f const& up) {
|
||||
Vec3f const f = (center - eye).normalized();
|
||||
Vec3f const s = f.cross(up).normalized();
|
||||
@@ -115,6 +118,15 @@ public:
|
||||
return (voxl >= 0 && voxl.x < width && voxl.y < height && voxl.z < depth);
|
||||
}
|
||||
|
||||
std::vector<Vec3f> genPixelDirs(Vec3f pos, Vec3f dir, size_t imgWidth, size_t imgHeight, float fov) {
|
||||
std::vector<Vec3f> dirs(imgWidth * imgHeight);
|
||||
float fovRad = radians(fov);
|
||||
float tanFov = tan(fovRad * 0.5);
|
||||
float aspect = static_cast<float>(imgWidth) / static_cast<float>(imgHeight);
|
||||
Vec3f worldUp(0, 1, 0);
|
||||
Vec3f camRight = worldUp.cross(dir).normalized();
|
||||
}
|
||||
|
||||
Vec3f perPixelRayDir(size_t x, size_t y, size_t imgWidth, size_t imgHeight, const Camera& cam) const {
|
||||
float normedX = (x + 0.5) / imgWidth * 2 - 1;
|
||||
float normedY = 1 - (y+0.5) / imgHeight * 2;
|
||||
@@ -142,68 +154,71 @@ public:
|
||||
step.z = (rayDir.z > 0) ? 1 : -1;
|
||||
Vec3f tMax;
|
||||
Vec3f tDelta;
|
||||
bool startOut = false;
|
||||
|
||||
//initialization
|
||||
tDelta.x = std::abs(1.0 / rayDir.x);
|
||||
tDelta.y = std::abs(1.0 / rayDir.y);
|
||||
tDelta.z = std::abs(1.0 / rayDir.z);
|
||||
tMax = mix(((rayOrigin - currentVoxel.toFloat()) / -rayDir).toFloat(), (((currentVoxel.toFloat() + 1) - rayOrigin) / rayDir).toFloat(), rayDir.mask([](float x, float value) { return x > 0; }, 0));
|
||||
tMax = mix(((rayOrigin - currentVoxel.toFloat()) / -rayDir).toFloat(),
|
||||
(((currentVoxel.toFloat() + 1) - rayOrigin) / rayDir).toFloat(),
|
||||
rayDir.mask([](float x, float value) { return x > 0; }, 0));
|
||||
|
||||
if (!inGrid(rayOrigin)) {
|
||||
/*
|
||||
The initialization phase begins by identifying the voxel in which the ray origin, →
|
||||
u, is found. If the ray origin is outside the grid, we find the point in which the ray enters the grid and take the adjacent voxel. The integer
|
||||
variables X and Y are initialized to the starting voxel coordinates. In addition, the variables stepX and
|
||||
stepY are initialized to either 1 or -1 indicating whether X and Y are incremented or decremented as the
|
||||
ray crosses voxel boundaries (this is determined by the sign of the x and y components of →
|
||||
v).
|
||||
Next, we determine the value of t at which the ray crosses the first vertical voxel boundary and
|
||||
store it in variable tMaxX. We perform a similar computation in y and store the result in tMaxY. The
|
||||
minimum of these two values will indicate how much we can travel along the ray and still remain in the
|
||||
current voxel.
|
||||
*/
|
||||
|
||||
startOut = true;
|
||||
Vec3f tBMin;
|
||||
Vec3f tBMax;
|
||||
|
||||
tBMin.x = (0.0 - rayOrigin.x) / rayDir.x;
|
||||
tBMax.x = (width - rayOrigin.x) / rayDir.x;
|
||||
if (tBMin.x > tBMax.x) std::swap(tBMin.x, tBMax.x);
|
||||
|
||||
tBMin.y = (0.0 - rayOrigin.y) / rayDir.y;
|
||||
tBMax.y = (height - rayOrigin.y) / rayDir.y;
|
||||
if (tBMin.y > tBMax.y) std::swap(tBMin.y, tBMax.y);
|
||||
|
||||
tBMin.z = (0.0 - rayOrigin.z) / rayDir.z;
|
||||
tBMax.z = (depth - rayOrigin.z) / rayDir.z;
|
||||
if (tBMin.z > tBMax.z) std::swap(tBMin.z, tBMax.z);
|
||||
|
||||
float tEntry = tBMin.maxComp();
|
||||
float tExit = tBMax.minComp();
|
||||
|
||||
if (tEntry > tExit || tExit < 0.0) return false;
|
||||
if (tEntry < 0.0) tEntry = 0.0;
|
||||
|
||||
if (tEntry > 0.0) {
|
||||
rayOrigin = rayOrigin + rayDir * tEntry;
|
||||
currentVoxel = rayOrigin.floorToT();
|
||||
tMax = mix(((currentVoxel.toFloat() + 1) - rayOrigin) / rayDir, (rayOrigin - currentVoxel) / -rayDir, rayDir.mask([](float x, float value) { return x > 0; }, 0) );
|
||||
tMax = mix(((currentVoxel.toFloat() + 1) - rayOrigin) / rayDir,
|
||||
(rayOrigin - currentVoxel) / -rayDir,
|
||||
rayDir.mask([](float x, float value) { return x > 0; }, 0));
|
||||
}
|
||||
}
|
||||
|
||||
// if (startOut && !inGrid(currentVoxel)) {
|
||||
// std::cout << "grid edge not found. " << currentVoxel << std::endl;
|
||||
// }
|
||||
|
||||
float aalpha = 0.0;
|
||||
bool hit = false;
|
||||
float tDist = 0.0;
|
||||
|
||||
/*
|
||||
Finally, we compute tDeltaX and tDeltaY. TDeltaX indicates how far along the ray we must move
|
||||
(in units of t) for the horizontal component of such a movement to equal the width of a voxel. Similarly,
|
||||
we store in tDeltaY the amount of movement along the ray which has a vertical component equal to the
|
||||
height of a voxel.
|
||||
*/
|
||||
// Main DDA loop
|
||||
while (inGrid(currentVoxel) && tDist < maxDistance) {
|
||||
Voxel& voxel = get(currentVoxel);
|
||||
|
||||
// Ignore alpha - treat any voxel with active > 0 as solid
|
||||
if (voxel.active > EPSILON) {
|
||||
Vec3f voxelColor(static_cast<float>(voxel.color.x / 255.0), static_cast<float>(voxel.color.y / 255.0), static_cast<float>(voxel.color.z / 255.0));
|
||||
float contribution = voxel.active * (1.0 - aalpha);
|
||||
hitColor = hitColor + voxelColor * contribution;
|
||||
aalpha += contribution;
|
||||
// Convert color from 0-255 to 0-1 range
|
||||
Vec3f voxelColor(
|
||||
static_cast<float>(voxel.color.x / 255.0),
|
||||
static_cast<float>(voxel.color.y / 255.0),
|
||||
static_cast<float>(voxel.color.z / 255.0)
|
||||
);
|
||||
|
||||
// No alpha blending - just take the first solid voxel's color
|
||||
hitColor = voxelColor;
|
||||
hitPos = rayOrigin + rayDir * tDist;
|
||||
|
||||
// Determine which face was hit
|
||||
if (tMax.x <= tMax.y && tMax.x <= tMax.z) {
|
||||
hitNormal = Vec3f(-step.x, 0.0, 0.0);
|
||||
} else if (tMax.y <= tMax.x && tMax.y <= tMax.z) {
|
||||
@@ -211,11 +226,11 @@ public:
|
||||
} else {
|
||||
hitNormal = Vec3f(0.0, 0.0, -step.z);
|
||||
}
|
||||
}
|
||||
if (aalpha > EPSILON) {
|
||||
hit = true;
|
||||
|
||||
return true; // Return immediately on first solid hit
|
||||
}
|
||||
|
||||
// Move to next voxel
|
||||
if (tMax.x < tMax.y) {
|
||||
if (tMax.x < tMax.z) {
|
||||
tDist = tMax.x;
|
||||
@@ -238,11 +253,124 @@ public:
|
||||
}
|
||||
}
|
||||
}
|
||||
if (aalpha > EPSILON) {
|
||||
std::cout << "hit at: " << currentVoxel << " with value of " << aalpha << std::endl;
|
||||
}
|
||||
return hit;
|
||||
|
||||
return false;
|
||||
}
|
||||
// bool rayCast(const Ray3f& ray, float maxDistance, Vec3f hitPos, Vec3f hitNormal, Vec3f& hitColor) {
|
||||
// hitColor = Vec3f(0,0,0);
|
||||
// Vec3f rayDir = ray.direction;
|
||||
// Vec3f rayOrigin = ray.origin;
|
||||
// Vec3T currentVoxel = rayOrigin.floorToT();
|
||||
// Vec3i step;
|
||||
// step.x = (rayDir.x > 0) ? 1 : -1;
|
||||
// step.y = (rayDir.y > 0) ? 1 : -1;
|
||||
// step.z = (rayDir.z > 0) ? 1 : -1;
|
||||
// Vec3f tMax;
|
||||
// Vec3f tDelta;
|
||||
// bool startOut = false;
|
||||
|
||||
// tDelta.x = std::abs(1.0 / rayDir.x);
|
||||
// tDelta.y = std::abs(1.0 / rayDir.y);
|
||||
// tDelta.z = std::abs(1.0 / rayDir.z);
|
||||
// tMax = mix(((rayOrigin - currentVoxel.toFloat()) / -rayDir).toFloat(), (((currentVoxel.toFloat() + 1) - rayOrigin) / rayDir).toFloat(), rayDir.mask([](float x, float value) { return x > 0; }, 0));
|
||||
// if (!inGrid(rayOrigin)) {
|
||||
// startOut = true;
|
||||
// /*
|
||||
// The initialization phase begins by identifying the voxel in which the ray origin, →
|
||||
// u, is found. If the ray origin is outside the grid, we find the point in which the ray enters the grid and take the adjacent voxel. The integer
|
||||
// variables X and Y are initialized to the starting voxel coordinates. In addition, the variables stepX and
|
||||
// stepY are initialized to either 1 or -1 indicating whether X and Y are incremented or decremented as the
|
||||
// ray crosses voxel boundaries (this is determined by the sign of the x and y components of →
|
||||
// v).
|
||||
// Next, we determine the value of t at which the ray crosses the first vertical voxel boundary and
|
||||
// store it in variable tMaxX. We perform a similar computation in y and store the result in tMaxY. The
|
||||
// minimum of these two values will indicate how much we can travel along the ray and still remain in the
|
||||
// current voxel.
|
||||
// */
|
||||
|
||||
// Vec3f tBMin;
|
||||
// Vec3f tBMax;
|
||||
// tBMin.x = (0.0 - rayOrigin.x) / rayDir.x;
|
||||
// tBMax.x = (width - rayOrigin.x) / rayDir.x;
|
||||
// if (tBMin.x > tBMax.x) std::swap(tBMin.x, tBMax.x);
|
||||
// tBMin.y = (0.0 - rayOrigin.y) / rayDir.y;
|
||||
// tBMax.y = (height - rayOrigin.y) / rayDir.y;
|
||||
// if (tBMin.y > tBMax.y) std::swap(tBMin.y, tBMax.y);
|
||||
// tBMin.z = (0.0 - rayOrigin.z) / rayDir.z;
|
||||
// tBMax.z = (depth - rayOrigin.z) / rayDir.z;
|
||||
// if (tBMin.z > tBMax.z) std::swap(tBMin.z, tBMax.z);
|
||||
// float tEntry = tBMin.maxComp();
|
||||
// float tExit = tBMax.minComp();
|
||||
// if (tEntry > tExit || tExit < 0.0) return false;
|
||||
// if (tEntry < 0.0) tEntry = 0.0;
|
||||
|
||||
// if (tEntry > 0.0) {
|
||||
// rayOrigin = rayOrigin + rayDir * tEntry;
|
||||
// currentVoxel = rayOrigin.floorToT();
|
||||
// tMax = mix(((currentVoxel.toFloat() + 1) - rayOrigin) / rayDir, (rayOrigin - currentVoxel) / -rayDir, rayDir.mask([](float x, float value) { return x > 0; }, 0) );
|
||||
// }
|
||||
|
||||
// }
|
||||
// if (startOut && !inGrid(currentVoxel)) std::cout << "grid edge not found. " << currentVoxel << std::endl;
|
||||
|
||||
// float aalpha = 0.0;
|
||||
// bool hit = false;
|
||||
// float tDist = 0.0;
|
||||
|
||||
// /*
|
||||
// Finally, we compute tDeltaX and tDeltaY. TDeltaX indicates how far along the ray we must move
|
||||
// (in units of t) for the horizontal component of such a movement to equal the width of a voxel. Similarly,
|
||||
// we store in tDeltaY the amount of movement along the ray which has a vertical component equal to the
|
||||
// height of a voxel.
|
||||
// */
|
||||
// while (inGrid(currentVoxel) && tDist < maxDistance) {
|
||||
// Voxel& voxel = get(currentVoxel);
|
||||
|
||||
// if (voxel.active > EPSILON) {
|
||||
// Vec3f voxelColor(static_cast<float>(voxel.color.x / 255.0), static_cast<float>(voxel.color.y / 255.0), static_cast<float>(voxel.color.z / 255.0));
|
||||
// float contribution = voxel.active * (1.0 - aalpha);
|
||||
// hitColor = hitColor + voxelColor * contribution;
|
||||
// aalpha += contribution;
|
||||
// hitPos = rayOrigin + rayDir * tDist;
|
||||
// if (tMax.x <= tMax.y && tMax.x <= tMax.z) {
|
||||
// hitNormal = Vec3f(-step.x, 0.0, 0.0);
|
||||
// } else if (tMax.y <= tMax.x && tMax.y <= tMax.z) {
|
||||
// hitNormal = Vec3f(0.0, -step.y, 0.0);
|
||||
// } else {
|
||||
// hitNormal = Vec3f(0.0, 0.0, -step.z);
|
||||
// }
|
||||
// }
|
||||
// if (aalpha > EPSILON) {
|
||||
// hit = true;
|
||||
// }
|
||||
|
||||
// if (tMax.x < tMax.y) {
|
||||
// if (tMax.x < tMax.z) {
|
||||
// tDist = tMax.x;
|
||||
// tMax.x += tDelta.x;
|
||||
// currentVoxel.x += step.x;
|
||||
// } else {
|
||||
// tDist = tMax.z;
|
||||
// tMax.z += tDelta.z;
|
||||
// currentVoxel.z += step.z;
|
||||
// }
|
||||
// } else {
|
||||
// if (tMax.y < tMax.z) {
|
||||
// tDist = tMax.y;
|
||||
// tMax.y += tDelta.y;
|
||||
// currentVoxel.y += step.y;
|
||||
// } else {
|
||||
// tDist = tMax.z;
|
||||
// tMax.z += tDelta.z;
|
||||
// currentVoxel.z += step.z;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// // if (aalpha > EPSILON) {
|
||||
// // std::cout << "hit at: " << currentVoxel << " with value of " << aalpha << std::endl;
|
||||
// // }
|
||||
// return hit;
|
||||
// }
|
||||
|
||||
size_t getWidth() const {
|
||||
return width;
|
||||
|
||||
Reference in New Issue
Block a user