A demo for mesh-voxel conversion
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

85 lines
3.0 KiB

#pragma once
#include <vector>
#include "Intersection.hpp"
class VoxelGrid {
private:
int width, height, depth, xySize;
Vec3<float> cellSize;
AABB aabb;
std::vector<uint8_t> data; // 每个体素只占用1 bit
public:
VoxelGrid(const AABB &aabb, const Vec3<float> &cellSize)
: cellSize(cellSize) {
// 根据 AABB 和 cellSize 计算宽、高、深
width = static_cast<int>(std::lround((aabb.max.x - aabb.min.x) / cellSize.x));
height = static_cast<int>(std::lround((aabb.max.y - aabb.min.y) / cellSize.y));
depth = static_cast<int>(std::lround((aabb.max.z - aabb.min.z) / cellSize.z));
xySize = width * height;
int totalSize = (xySize * depth + 7) / 8; // 每8个体素占用一个字节
data.resize(totalSize, 0);
this->aabb = aabb; // 使用传入的 AABB
}
VoxelGrid() = default;
// 根据索引获取单元格的 AABB
AABB getCellAABB(int x, int y, int z) const {
Vec3<float> cellMin(x * cellSize.x, y * cellSize.y, z * cellSize.z);
Vec3<float> cellMax((x + 1) * cellSize.x, (y + 1) * cellSize.y, (z + 1) * cellSize.z);
return AABB(cellMin, cellMax) + aabb.min;
}
// 根据索引写入
void setVoxel(int x, int y, int z, bool value) {
assert(x >= 0 && x < width && y >= 0 && y < height && z >= 0 && z < depth);
int index = x + y * width + z * xySize;
int byteIndex = index / 8;
int bitIndex = index % 8;
if (value) {
data[byteIndex] |= (1 << bitIndex); // 设置为1
} else {
data[byteIndex] &= ~(1 << bitIndex); // 设置为0
}
}
// 根据索引读取
bool getVoxel(int x, int y, int z) const {
assert(x >= 0 && x < width && y >= 0 && y < height && z >= 0 && z < depth);
int index = x + y * width + z * xySize;
int byteIndex = index / 8;
int bitIndex = index % 8;
return (data[byteIndex] >> bitIndex) & 1; // 返回位值
}
static VoxelGrid generateFromMesh(const Mesh &mesh, const Vec3<float> &cellSize) {
auto sceneAABB = mesh.getAABB();
auto voxelGrid = VoxelGrid(sceneAABB, cellSize);
BVH bvh(mesh);
int solvedVoxel = 0;
for (int z = 0; z < voxelGrid.depth; ++z) {
for (int y = 0; y < voxelGrid.height; ++y) {
for (int x = 0; x < voxelGrid.width; ++x) {
auto start = voxelGrid.getCellAABB(x, y, z).center();
auto dir = Vec3f(1, 2, 3).norm();
if (bvh.intersectWithRay({start, dir}) % 2 == 1) {
voxelGrid.setVoxel(x, y, z, true);
} else {
voxelGrid.setVoxel(x, y, z, false);
}
solvedVoxel++;
if (solvedVoxel % int(1e5) == 0) {
std::cout << "Solved " << solvedVoxel << " voxels." << std::endl;
}
}
}
}
return voxelGrid;
}
};