finally fixed bmp bgr/rgb bug.

This commit is contained in:
Yggdrasil75
2026-01-07 13:12:19 -05:00
parent 7c569afd46
commit 65f2464c70
5 changed files with 131 additions and 350 deletions

View File

@@ -66,12 +66,12 @@ bool renderView(const std::string& filename, VoxelGrid& grid, const Vec3f& posit
size_t height = RENDER_HEIGHT; size_t height = RENDER_HEIGHT;
// Render the view // Render the view
//frame output = grid.renderFrame(position, direction, up, 40, RENDER_WIDTH, RENDER_HEIGHT); frame output = grid.renderFrame(position, direction, up, 40, RENDER_WIDTH, RENDER_HEIGHT);
grid.renderOut(renderBuffer, width, height, cam); //grid.renderOut(renderBuffer, width, height, cam);
// Save to BMP // Save to BMP
//bool success = BMPWriter::saveBMP(filename, output); bool success = BMPWriter::saveBMP(filename, output);
bool success = BMPWriter::saveBMP(filename, renderBuffer, width, height); //bool success = BMPWriter::saveBMP(filename, renderBuffer, width, height);
// if (success) { // if (success) {
// std::cout << "Saved: " << filename << std::endl; // std::cout << "Saved: " << filename << std::endl;
@@ -143,52 +143,52 @@ int main() {
Vec3f baseDirection(0, 0, -1); // Looking towards negative Z (towards center) Vec3f baseDirection(0, 0, -1); // Looking towards negative Z (towards center)
Vec3f up(0, 1, 0); Vec3f up(0, 1, 0);
// Render frames around 180 degrees // // Render frames around 180 degrees
for (int i = 0; i <= numFrames; i++) { // for (int i = 0; i <= numFrames; i++) {
float angle = (float)i / numFrames * M_PI; // 0 to π (180 degrees) // float angle = (float)i / numFrames * M_PI; // 0 to π (180 degrees)
// Rotate camera position around Y axis // // Rotate camera position around Y axis
Vec3f rotatedPos = rotateY(basePosition, angle); // Vec3f rotatedPos = rotateY(basePosition, angle);
Vec3f finalPos = gridCenter + rotatedPos; // Vec3f finalPos = gridCenter + rotatedPos;
//Vec3f rotatedDir = rotateY(baseDirection, angle); // //Vec3f rotatedDir = rotateY(baseDirection, angle);
Vec3f rotatedDir = (gridCenter - finalPos).normalized(); // Vec3f rotatedDir = (gridCenter - finalPos).normalized();
// Create filename with frame number // // Create filename with frame number
char filename[256]; // char filename[256];
snprintf(filename, sizeof(filename), "output/framey_%03d.bmp", i); // snprintf(filename, sizeof(filename), "output/framey_%03d.bmp", i);
// std::cout << "Rendering frame " << i << "/" << numFrames // // std::cout << "Rendering frame " << i << "/" << numFrames
// << " (angle: " << (angle * 360.0f / M_PI) << " degrees)" << std::endl; // // << " (angle: " << (angle * 360.0f / M_PI) << " degrees)" << std::endl;
renderView(filename, grid, finalPos, rotatedDir, up); // renderView(filename, grid, finalPos, rotatedDir, up);
} // }
basePosition = Vec3f(0, 0, cameraDistance); // basePosition = Vec3f(0, 0, cameraDistance);
baseDirection = Vec3f(0, 0, -1); // baseDirection = Vec3f(0, 0, -1);
up = Vec3f(0, 1, 0); // up = Vec3f(0, 1, 0);
for (int i = 0; i <= numFrames; i++) { // for (int i = 0; i <= numFrames; i++) {
float angle = (float)i / numFrames * M_PI; // 0 to π (180 degrees) // float angle = (float)i / numFrames * M_PI; // 0 to π (180 degrees)
// Rotate camera position around Y axis // // Rotate camera position around Y axis
Vec3f rotatedPos = rotateZ(basePosition, angle); // Vec3f rotatedPos = rotateZ(basePosition, angle);
Vec3f finalPos = gridCenter + rotatedPos; // Vec3f finalPos = gridCenter + rotatedPos;
//Vec3f rotatedDir = rotateY(baseDirection, angle); // //Vec3f rotatedDir = rotateY(baseDirection, angle);
Vec3f rotatedDir = (gridCenter - finalPos).normalized(); // Vec3f rotatedDir = (gridCenter - finalPos).normalized();
// Create filename with frame number // // Create filename with frame number
char filename[256]; // char filename[256];
snprintf(filename, sizeof(filename), "output/framez_%03d.bmp", i); // snprintf(filename, sizeof(filename), "output/framez_%03d.bmp", i);
// std::cout << "Rendering frame " << i << "/" << numFrames // // std::cout << "Rendering frame " << i << "/" << numFrames
// << " (angle: " << (angle * 360.0f / M_PI) << " degrees)" << std::endl; // // << " (angle: " << (angle * 360.0f / M_PI) << " degrees)" << std::endl;
renderView(filename, grid, finalPos, rotatedDir, up); // renderView(filename, grid, finalPos, rotatedDir, up);
} // }
basePosition = Vec3f(0, 0, cameraDistance); // basePosition = Vec3f(0, 0, cameraDistance);
baseDirection = Vec3f(0, 0, -1); // baseDirection = Vec3f(0, 0, -1);
up = Vec3f(0, 1, 0); // up = Vec3f(0, 1, 0);
for (int i = 0; i <= numFrames; i++) { for (int i = 0; i <= numFrames; i++) {
float angle = (float)i / numFrames * M_PI; // 0 to π (180 degrees) float angle = (float)i / numFrames * M_PI; // 0 to π (180 degrees)
@@ -203,8 +203,8 @@ int main() {
char filename[256]; char filename[256];
snprintf(filename, sizeof(filename), "output/framex_%03d.bmp", i); snprintf(filename, sizeof(filename), "output/framex_%03d.bmp", i);
// std::cout << "Rendering frame " << i << "/" << numFrames std::cout << "Rendering frame " << i << "/" << numFrames
// << " (angle: " << (angle * 360.0f / M_PI) << " degrees)" << std::endl; << " (angle: " << (angle * 360.0f / M_PI) << " degrees)" << std::endl;
renderView(filename, grid, finalPos, rotatedDir, up); renderView(filename, grid, finalPos, rotatedDir, up);
} }

View File

@@ -28,6 +28,7 @@ struct Camera {
class VoxelGrid { class VoxelGrid {
private: private:
double binSize = 1;
Vec3T gridSize; Vec3T gridSize;
//size_t width, height, depth; //size_t width, height, depth;
std::vector<Voxel> voxels; std::vector<Voxel> voxels;
@@ -67,55 +68,6 @@ private:
return Result; return Result;
} }
std::pair<float,float> rayBoxIntersect(const Vec3f& origin, const Vec3f& direction) {
Vec3f tBMin = Vec3f(0,0,0);
Vec3f tBMax = gridSize.toFloat();
float tmin = -INF;
float tmax = INF;
Vec3f invDir = direction.safeInverse();
bool allParallel = true;
for (int i = 0; i < 3; ++i) {
if (abs(direction[i]) < EPSILON) {
if (!(origin[i] < tBMin[i] || origin[i] > tBMax[i])) continue;
}
allParallel = false;
float t1 = (tBMin[i] - origin[i]) * invDir[i];
float t2 = (tBMax[i] - origin[i]) * invDir[i];
if (t1 > t2) std::swap(t1, t2);
if (t1 > tmin) tmin = t1;
if (t2 < tmax) tmax = t2;
if (tmin > tmax) return std::make_pair(0.0f, 0.0f);
}
if (allParallel) {
return std::make_pair(0.0f, 0.0f);
}
if (tmax < 0) return std::make_pair(0.0f, 0.0f);
return std::make_pair(tmin, tmax);
}
//used to prevent division by 0 issues
bool specialCases(const Vec3f& origin, const Vec3f& direction, float maxDist, Vec3f& hitColor) {
float stepSize = 0.5;
int maxSteps = maxDist/stepSize;
for (int step = 0; step < maxSteps; ++step) {
float t = step * stepSize;
Vec3f pos = Vec3f(origin + direction * t);
Vec3T voxelCoords = pos.floorToT();
if (inGrid(voxelCoords)) {
Voxel cv = get(voxelCoords);
if (cv.active > EPSILON) {
hitColor = cv.color.toFloat();
std::cout << "hit in special case at: " << voxelCoords << std::endl;
return true;
}
}
}
return false;
}
public: public:
VoxelGrid(size_t w, size_t h, size_t d) : gridSize(w,h,d) { VoxelGrid(size_t w, size_t h, size_t d) : gridSize(w,h,d) {
voxels.resize(w * h * d); voxels.resize(w * h * d);
@@ -177,180 +129,62 @@ public:
return (voxl >= 0 && voxl.x < gridSize.x && voxl.y < gridSize.y && voxl.z < gridSize.z); return (voxl >= 0 && voxl.x < gridSize.x && voxl.y < gridSize.y && voxl.z < gridSize.z);
} }
std::vector<Vec3f> genPixelDirs(const Vec3f& pos, const Vec3f& dir, size_t imgWidth, size_t imgHeight, float fov) { void voxelTraverse(const Vec3d& origin, const Vec3d& end, std::vector<Vec3T>& visitedVoxel) {
std::vector<Vec3f> dirs(imgWidth * imgHeight); Vec3T cv = (origin / binSize).floorToT();
float fovRad = radians(fov); Vec3T lv = (end / binSize).floorToT();
float tanFov = tan(fovRad * 0.5); Vec3d ray = end - origin;
float aspect = static_cast<float>(imgWidth) / static_cast<float>(imgHeight); Vec3f step = Vec3f(ray.x >= 0 ? 1 : -1, ray.y >= 0 ? 1 : -1, ray.z >= 0 ? 1 : -1);
Vec3f worldUp(0, 1, 0); Vec3d nextVox = cv.toDouble() + step * binSize;
Vec3f camRight = worldUp.cross(dir).normalized(); Vec3d tMax = Vec3d(ray.x != 0 ? (nextVox.x - origin.x) / ray.x : INF,
Vec3f camUp = dir.cross(camRight).normalized(); ray.y != 0 ? (nextVox.y - origin.y) / ray.y : INF,
ray.z != 0 ? (nextVox.z-origin.z) / ray.z : INF);
Vec3d tDelta = Vec3d(ray.x != 0 ? binSize / ray.x * step.x : INF,
ray.y != 0 ? binSize / ray.y * step.y : INF,
ray.z != 0 ? binSize / ray.z * step.z : INF);
float imgWidthInv = 1 / (imgWidth - 1); Vec3T diff(0,0,0);
float imgHeightInv = 1 / (imgHeight - 1); bool negRay = false;
float aspectTanFov = aspect * tanFov; if (cv.x != lv.x && ray.x < 0) {
diff.x = diff.x--;
for (int y = 0; y < imgHeight; ++y) { negRay = true;
float ndcY = 1 - (2 * y * imgHeightInv);
float screenY = ndcY * tanFov;
for (int x = 0; x < imgWidth; ++x) {
float ndcX = (2 * x * imgWidthInv) - 1;
float screenX = ndcX * aspectTanFov;
Vec3f dir = (camRight * screenX + camUp * screenY + dir).normalized();
dirs[y*imgWidth+x] = dir;
} }
if (cv.y != lv.y && ray.y < 0) {
diff.y = diff.y--;
negRay = true;
} }
return dirs; if (cv.z != lv.z && ray.z < 0) {
diff.z = diff.z--;
negRay = true;
} }
Vec3f perPixelRayDir(size_t x, size_t y, size_t imgWidth, size_t imgHeight, const Camera& cam) const { if (negRay) {
float normedX = (x + 0.5) / imgWidth * 2 - 1; cv += diff;
float normedY = 1 - (y+0.5) / imgHeight * 2; visitedVoxel.push_back(cv);
float aspect = imgWidth / imgHeight;
float fovRad = cam.fov * M_PI / 180;
float scale = tan(fovRad * 0.5);
Vec3f rayDirCam = Vec3f(normedX * aspect * scale, normedY * scale, -1).normalized();
Vec3f eye = cam.posfor.origin;
Vec3f center = eye + cam.posfor.direction;
Mat4f viewMat = lookAt(eye, center, cam.up);
Mat4f invViewMat = viewMat.inverse();
Vec3f rayDirWorld = invViewMat.transformDirection(rayDirCam);
return rayDirWorld.normalized();
} }
bool castRay(const Vec3f& origin, const Vec3f& direction, float maxDist, Vec3f& hitColor) { while (lv != cv && inGrid(cv)) {
Vec3f dir = direction.normalized(); if (get(cv).active) {
Vec3T pos = origin.floorToT(); visitedVoxel.push_back(cv);
Vec3i8 step = Vec3i(dir.x > 0 ? 1 : -1, dir.y > 0 ? 1 : -1, dir.z > 0 ? 1 : -1);
Vec3f tMax;
Vec3f tDelta;
if (abs(dir.x) > EPSILON) {
tMax.x = static_cast<float>(static_cast<size_t>(pos.x) + (step.x > 0 ? 1 : 0) - pos.x) / dir.x;
tDelta.x = step.x / dir.x;
} else {
tMax.x = INF;
tDelta.x = INF;
} }
if (abs(dir.y) > EPSILON) { if (tMax.x < tMax.y) {
tMax.y = static_cast<float>(static_cast<size_t>(pos.y) + (step.y > 0 ? 1 : 0) - pos.y) / dir.y; if (tMax.x < tMax.z) {
tDelta.y = step.y / dir.y; cv.x += step.x;
} else {
tMax.y = INF;
tDelta.y = INF;
}
if (abs(dir.z) > EPSILON) {
tMax.z = static_cast<float>(static_cast<size_t>(pos.z) + (step.z > 0 ? 1 : 0) - pos.z) / dir.z;
tDelta.z = step.z / dir.z;
} else {
tMax.z = INF;
tDelta.z = INF;
}
auto intersect = rayBoxIntersect(origin, dir);
float tEntry = intersect.first;
float tExit = intersect.second;
if (tEntry <= 0 && tExit <= 0) return false;
if (tEntry > maxDist) return false;
float dist = 0;
while (dist < maxDist) {
if (inGrid(pos)) {
Voxel cv = get(pos);
if (cv.active) {
Vec3f norm = Vec3f(0,0,0);
if (tMax.x <= tMax.y && tMax.x <= tMax.z) norm.x = -step.x;
else if (tMax.y <= tMax.x && tMax.y <= tMax.z) norm.y = -step.y;
else norm.z = -step.z;
hitColor = cv.color.toFloat() / 255;
return true;
}
}
if (tMax.x <= tMax.y && tMax.x <= tMax.z) {
pos.x += step.x;
dist += tDelta.x;
//dist = tMax.x;
tMax.x += tDelta.x; tMax.x += tDelta.x;
} else if (tMax.y <= tMax.x && tMax.y <= tMax.z) { } else {
pos.y += step.y; cv.z += step.z;
//dist = tMax.y; tMax.z += tDelta.z;
dist += tDelta.y; }
} else {
if (tMax.y < tMax.z) {
cv.y += step.y;
tMax.y += tDelta.y; tMax.y += tDelta.y;
} else { } else {
pos.z += step.z; cv.z += step.z;
//dist = tMax.z;
dist += tDelta.z;
tMax.z += tDelta.z; tMax.z += tDelta.z;
} }
} }
return false;
} }
return; // &&visitedVoxel;
bool rayCast(const Vec3f& origin, const Vec3f& direction, float maxDist, Vec3f& hitColor) {
Vec3f dir = direction.normalized();
if (abs(dir.length()) < EPSILON) return false;
if (dir.x == 0 || dir.y == 0 || dir.z == 0) {
return specialCases(origin, dir, maxDist, hitColor);
}
float tStart;
Vec3f invDir = dir.safeInverse();
Vec3T currentVoxel = origin.floorToT();
if (!inGrid(currentVoxel)) {
std::pair<float,float> re = rayBoxIntersect(origin, dir);
float tEntry = re.first;
float tExit = re.second;
if (tEntry < EPSILON || tExit < EPSILON) return false;
if (tEntry > maxDist) return false;
tStart = tEntry;
}
Vec3f gridOrig = origin + dir * tStart;
currentVoxel = gridOrig.floorToT();
Vec3i8 step = Vec3i8(dir.x >= 0 ? 1 : -1, dir.y >= 0 ? 1 : -1, dir.z >= 0 ? 1 : -1);
Vec3f tMax;
float tDist = tStart;
for (int i = 0; i < 3; i++) {
if (step[i] > 0) {
tMax[i] = ((currentVoxel[i] + 1) - gridOrig[i]) * invDir[i];
} else {
tMax[i] = (currentVoxel[i] - gridOrig[i]) * invDir[i];
}
}
Vec3f tDelta = invDir.abs();
float aalpha = 0;
while (inGrid(currentVoxel) && aalpha < 1 && tDist <= maxDist) {
Voxel cv = get(currentVoxel);
if (cv.active > EPSILON) {
float alpha = cv.active * (1.0f - aalpha);
Vec3f voxelColor = cv.color.toFloat() / 255.0f;
hitColor = hitColor + voxelColor * alpha;
aalpha += cv.active;
}
if (tMax.x < tMax.y && tMax.x < tMax.z) {
tDist = tDist + tDelta.x;
if (tMax.x > maxDist) break;
currentVoxel.x += step.x;
tMax.x += tDelta.x;
} else if (tMax.y < tMax.z) {
tDist = tDist + tDelta.y;
currentVoxel.y += step.y;
tMax.y += tDelta.y;
}
else {
tDist = tDist + tDelta.z;
currentVoxel.z += step.z;
tMax.z += tDelta.z;
}
}
if (aalpha > EPSILON) {
//std::cout << "hit in normal case " << " due to any alpha" << std::endl;
return true;
} else return false;
} }
size_t getWidth() const { size_t getWidth() const {
@@ -363,109 +197,53 @@ public:
return gridSize.z; return gridSize.z;
} }
frame renderFrame(const Vec3f& CamPos, const Vec3f& lookAt, const Vec3f& up, float fov, size_t outW, size_t outH) { frame renderFrame(const Vec3f& CamPos, const Vec3f& dir, const Vec3f& up, float fov, size_t outW, size_t outH) {
TIME_FUNCTION; TIME_FUNCTION;
Vec3f forward = (lookAt - CamPos).normalized(); Vec3f forward = (dir - CamPos).normalized();
Vec3f right = forward.cross(up).normalized(); Vec3f right = forward.cross(up).normalized();
Vec3f upCor = right.cross(forward).normalized(); Vec3f upCor = right.cross(forward).normalized();
float aspect = static_cast<float>(outW) / outH; float aspect = static_cast<float>(outW) / static_cast<float>(outH);
float fovRad = radians(fov); float fovRad = radians(fov);
float viewH = 2 * tan(fovRad / 2); float viewH = 2 * tan(fovRad / 2);
float viewW = viewH * aspect; float viewW = viewH * aspect;
float maxDist = gridSize.lengthSquared() / 2; float maxDist = std::sqrt(gridSize.lengthSquared()) * binSize;
frame outFrame = frame(outH,outW, frame::colormap::RGB); frame outFrame(outH, outW, frame::colormap::RGB);
std::vector<uint8_t> colorBuffer(outW * outH * 3); std::vector<uint8_t> colorBuffer(outW * outH * 3);
#pragma omp parallel for #pragma omp parallel for
for (size_t y = 0; y < outH; y++) { for (size_t y = 0; y < outH; y++) {
float v = (y + 0.5) / outH - 0.5; float v = (static_cast<float>(y) / static_cast<float>(outH - 1)) - 0.5f;
for (size_t x = 0; x < outW; x++) { for (size_t x = 0; x < outW; x++) {
float u = (x + 0.5) / outW - 0.5; std::vector<Vec3T> hitVoxels;
Vec3f rayDir = (forward + right * (u * viewW) + upCor * (v * viewH)).normalized(); float u = (static_cast<float>(x) / static_cast<float>(outW - 1)) - 0.5f;
Vec3f hitColor = Vec3f(0,0,0); Vec3f rayDirWorld = (forward + right * (u * viewW) + upCor * (v * viewH)).normalized();
bool hit = castRay(CamPos, rayDir, maxDist, hitColor); Vec3f rayEnd = CamPos + rayDirWorld * maxDist;
size_t idx = (y*outH+x) * 3; Vec3d rayStartGrid = CamPos.toDouble() / binSize;
if (!hit) { Vec3d rayEndGrid = rayEnd.toDouble() / binSize;
hitColor = Vec3f(0.1,0.1,1.0f); voxelTraverse(rayStartGrid, rayEndGrid, hitVoxels);
} else { Vec3ui8 hitColor(10, 10, 255);
std::cout << "hit"; for (const Vec3T& voxelPos : hitVoxels) {
} if (inGrid(voxelPos)) {
colorBuffer[idx + 0] = static_cast<uint8_t>(hitColor.x * 255); const Voxel& voxel = get(voxelPos);
colorBuffer[idx + 1] = static_cast<uint8_t>(hitColor.y * 255); if (voxel.active) {
colorBuffer[idx + 2] = static_cast<uint8_t>(hitColor.z * 255); hitColor = voxel.color;
break;
} }
} }
std::cout << std::endl; }
hitVoxels.clear();
hitVoxels.shrink_to_fit();
// Set pixel color in buffer
size_t idx = (y * outW + x) * 3;
colorBuffer[idx + 0] = hitColor.x;
colorBuffer[idx + 1] = hitColor.y;
colorBuffer[idx + 2] = hitColor.z;
}
}
outFrame.setData(colorBuffer); outFrame.setData(colorBuffer);
return outFrame; return outFrame;
} }
void renderOut(std::vector<uint8_t>& output, size_t& outwidth, size_t& outheight, const Camera& cam) {
TIME_FUNCTION;
Vec3f forward = (cam.posfor.direction - cam.posfor.origin).normalized();
Vec3f right = forward.cross(cam.up).normalized();
Vec3f upCor = right.cross(forward).normalized();
float aspect = outwidth / outheight;
float fovRad = radians(cam.fov);
float viewH = 2 * tan(fovRad / 2);
float viewW = viewH * aspect;
float maxDist = gridSize.lengthSquared() / 2;
//frame outFrame = frame(outH,outW, frame::colormap::RGB);
std::vector<uint8_t> colorBuffer(outwidth * outheight * 3);
#pragma omp parallel for
for (size_t y = 0; y < outheight; y++) {
float v = y * outheight;
for (size_t x = 0; x < outwidth; x++) {
float u = x * outwidth;
Vec3f rayDir = (forward + right * (u + viewW) + upCor * (v * viewH)).normalized();
Vec3f hitColor = Vec3f(0,0,0);
bool hit = castRay(cam.posfor.origin, rayDir, maxDist, hitColor);
size_t idx = (y*outheight+x) * 3;
if (!hit) {
hitColor = Vec3f(0.1,0.1,1.0f);
} else {
std::cout << "hit";
}
colorBuffer[idx + 0] = static_cast<uint8_t>(hitColor.x * 255);
colorBuffer[idx + 1] = static_cast<uint8_t>(hitColor.y * 255);
colorBuffer[idx + 2] = static_cast<uint8_t>(hitColor.z * 255);
}
}
std::cout << std::endl;
output = colorBuffer;
// TIME_FUNCTION;
// output.resize(outwidth * outheight * 3);
// Vec3f backgroundColor(0.1f, 0.1f, 1.0f);
// float maxDistance = sqrt(gridSize.lengthSquared()) * 2;
// //float maxDistance = std::sqrt(width*width + height*height + depth*depth) * 2.0f;
// // std::vector<Vec3f> dirs = genPixelDirs(cam.posfor.origin, cam.posfor.direction, outwidth, outheight, cam.fov);
// for (size_t y = 0; y < outheight; y++) {
// float yout = y * outwidth;
// for (size_t x = 0; x < outwidth; x++) {
// // Vec3f rayDir = dirs[y*outwidth + x];
// // Vec3f hitColor = Vec3f(0,0,0);
// Vec3f rayDir = perPixelRayDir(x, y, outwidth, outheight, cam);
// Ray3f ray(cam.posfor.origin, rayDir);
// Vec3f hitPos;
// Vec3f hitNorm;
// Vec3f hitColor;
// bool hit = castRay(cam.posfor.origin, rayDir, maxDistance, hitColor);
// Vec3f finalColor;
// if (!hit) {
// finalColor = backgroundColor;
// } else {
// finalColor = hitColor;
// }
// finalColor = finalColor.clamp(0, 1);
// size_t pixelIndex = (yout + x) * 3;
// output[pixelIndex + 0] = static_cast<uint8_t>(finalColor.x * 255);
// output[pixelIndex + 1] = static_cast<uint8_t>(finalColor.y * 255);
// output[pixelIndex + 2] = static_cast<uint8_t>(finalColor.z * 255);
// }
// }
}
}; };
#endif #endif

View File

@@ -133,9 +133,9 @@ public:
// Input is already BGR: pixels[i]=b, pixels[i+1]=g, pixels[i+2]=r // Input is already BGR: pixels[i]=b, pixels[i+1]=g, pixels[i+2]=r
// So we can copy directly // So we can copy directly
row[dstOffset] = srcRow[srcOffset]; // B row[dstOffset + 0] = srcRow[srcOffset + 2]; // B
row[dstOffset + 1] = srcRow[srcOffset + 1]; // G row[dstOffset + 1] = srcRow[srcOffset + 1]; // G
row[dstOffset + 2] = srcRow[srcOffset + 2]; // R row[dstOffset + 2] = srcRow[srcOffset + 0]; // R
} }
file.write(reinterpret_cast<const char*>(row.data()), rowSize); file.write(reinterpret_cast<const char*>(row.data()), rowSize);
} }

View File

@@ -247,7 +247,6 @@ public:
return Vec3<bool>(comp(x, other.x), comp(y, other.y), comp(z, other.z)); return Vec3<bool>(comp(x, other.x), comp(y, other.y), comp(z, other.z));
} }
Vec3 abs() const { Vec3 abs() const {
return Vec3(std::abs(x), std::abs(y), std::abs(z)); return Vec3(std::abs(x), std::abs(y), std::abs(z));
} }
@@ -268,6 +267,10 @@ public:
return Vec3<float>(static_cast<float>(x), static_cast<float>(y), static_cast<float>(z)); return Vec3<float>(static_cast<float>(x), static_cast<float>(y), static_cast<float>(z));
} }
Vec3<double> toDouble() const {
return Vec3<double>(static_cast<double>(x), static_cast<double>(y), static_cast<double>(z));
}
Vec3 ceil() const { Vec3 ceil() const {
return Vec3(std::ceil(x), std::ceil(y), std::ceil(z)); return Vec3(std::ceil(x), std::ceil(y), std::ceil(z));
} }

BIN
voxel_render.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 842 B