7uint8_t GreedyMesher::at(
const uint8_t *
v,
int x,
int y,
int z) {
12uint8_t GreedyMesher::neighborAt(
const uint8_t *voxels,
ChunkSampler sampler,
void *userData,
13 int chunkX,
int chunkY,
int chunkZ,
int nx,
int ny,
int nz) {
16 if (sampler)
return sampler(userData, chunkX, chunkY, chunkZ, nx, ny, nz);
20uint8_t GreedyMesher::outsideVoxel(
const uint8_t *voxels,
ChunkSampler sampler,
void *userData,
21 int chunkX,
int chunkY,
int chunkZ,
FaceDir dir,
int slice,
23 int x = 0,
y = 0,
z = 0;
31 default:
x = gu;
y = gv;
z = slice - 1;
break;
33 return neighborAt(voxels, sampler, userData, chunkX, chunkY, chunkZ,
x,
y,
z);
36uint8_t GreedyMesher::vertexAO(
const uint8_t *voxels,
ChunkSampler sampler,
void *userData,
37 int chunkX,
int chunkY,
int chunkZ,
FaceDir dir,
int slice,
int gu,
39 const uint8_t e1 = outsideVoxel(voxels, sampler, userData, chunkX, chunkY, chunkZ,
dir, slice,
41 const uint8_t e2 = outsideVoxel(voxels, sampler, userData, chunkX, chunkY, chunkZ,
dir, slice,
43 const uint8_t
d = outsideVoxel(voxels, sampler, userData, chunkX, chunkY, chunkZ,
dir, slice,
45 if (isSolid(e1) && isSolid(e2))
return 0;
46 return uint8_t(3 - (isSolid(e1) ? 1 : 0) - (isSolid(e2) ? 1 : 0) - (isSolid(
d) ? 1 : 0));
49uint32_t GreedyMesher::rectAOWord(
const uint8_t *voxels,
ChunkSampler sampler,
void *userData,
50 int chunkX,
int chunkY,
int chunkZ,
FaceDir dir,
int slice,
51 int x,
int y,
int z,
int w,
int h) {
56 gu[0] =
z; gv[0] =
y; gu[1] =
z +
w; gv[1] =
y;
57 gu[2] =
z +
w; gv[2] =
y +
h; gu[3] =
z; gv[3] =
y +
h;
60 gu[0] =
z +
w; gv[0] =
y; gu[1] =
z; gv[1] =
y;
61 gu[2] =
z; gv[2] =
y +
h; gu[3] =
z +
w; gv[3] =
y +
h;
64 gu[0] =
x; gv[0] =
z; gu[1] =
x +
w; gv[1] =
z;
65 gu[2] =
x +
w; gv[2] =
z +
h; gu[3] =
x; gv[3] =
z +
h;
68 gu[0] =
x; gv[0] =
z +
h; gu[1] =
x +
w; gv[1] =
z +
h;
69 gu[2] =
x +
w; gv[2] =
z; gu[3] =
x; gv[3] =
z;
72 gu[0] =
x +
w; gv[0] =
y; gu[1] =
x; gv[1] =
y;
73 gu[2] =
x; gv[2] =
y +
h; gu[3] =
x +
w; gv[3] =
y +
h;
77 gu[0] =
x; gv[0] =
y; gu[1] =
x +
w; gv[1] =
y;
78 gu[2] =
x +
w; gv[2] =
y +
h; gu[3] =
x; gv[3] =
y +
h;
82 for (
int i = 0; i < 4; ++i) {
84 uint32_t(vertexAO(voxels, sampler, userData, chunkX, chunkY, chunkZ,
dir, slice,
86 word |= ao << (2 * i);
92 std::vector<PackedRect> &out, std::vector<uint32_t> *aoOut,
93 const uint8_t *voxels,
ChunkSampler sampler,
void *userData,
94 int chunkX,
int chunkY,
int chunkZ) {
97 const int tex = mask[
v][
u];
109 for (
int k = 0; k <
w; ++k) {
110 if (mask[
v +
h][
u + k] != tex) {
118 for (
int dv = 0; dv <
h; ++dv)
119 for (
int du = 0; du <
w; ++du) mask[
v + dv][
u + du] = -1;
121 int x = 0,
y = 0,
z = 0;
152 aoOut->push_back(rectAOWord(voxels, sampler, userData, chunkX, chunkY, chunkZ,
153 dir, slice,
x,
y,
z, rw, rh));
162 void *samplerUserData,
int chunkX,
int chunkY,
int chunkZ,
163 std::vector<uint32_t> *aoOut) {
172 int x = 0,
y = 0,
z = 0;
173 int nx = 0, ny = 0, nz = 0;
240 const uint8_t
id = at(voxels,
x,
y,
z);
241 if (!isSolid(
id))
continue;
242 if (isSolid(neighborAt(voxels, sampler, samplerUserData, chunkX, chunkY, chunkZ,
249 greedy2D(mask,
dir,
s, out, aoOut, voxels, sampler, samplerUserData, chunkX, chunkY,
256 void *samplerUserData,
int chunkX,
int chunkY,
int chunkZ,
257 std::vector<uint32_t> aoOut[6]) {
260 if (aoOut) aoOut[i].clear();
261 meshFace(voxels,
FaceDir(i), outFaces[i], types, sampler, samplerUserData, chunkX, chunkY,
262 chunkZ, aoOut ? &aoOut[i] :
nullptr);
static void meshFace(const uint8_t *voxels, FaceDir dir, std::vector< PackedRect > &out, const CubeTypeRegistry &types=CubeTypeRegistry::empty(), ChunkSampler sampler=nullptr, void *samplerUserData=nullptr, int chunkX=0, int chunkY=0, int chunkZ=0, std::vector< uint32_t > *aoOut=nullptr)
Mesh a single face direction into out (appended; caller may clear).
static void meshChunk(const uint8_t *voxels, std::vector< PackedRect > outFaces[6], const CubeTypeRegistry &types=CubeTypeRegistry::empty(), ChunkSampler sampler=nullptr, void *samplerUserData=nullptr, int chunkX=0, int chunkY=0, int chunkZ=0, std::vector< uint32_t > aoOut[6]=nullptr)
Mesh all six faces. Clears and fills outFaces[6].
方块类型定义:名字、各面图集纹理、方向性、组合声明。 方向性方块在注册时按 orientation 绕 Y 轴展开成多个"具体类型"变体, 每个变体持有旋转后的各面纹理;渲染端只消费纹理 id,不接触 ...
constexpr int kChunkSize
Chunk edge length in voxels (fixed).
uint8_t resolveFaceTex(const CubeTypeRegistry &types, uint8_t id, FaceDir dir)
求某个体素在某面方向上的实际图集纹理 id。 未注册的 id 退化为“所有面 = 原 id”(向后兼容:体素值即纹理 id)。
constexpr int faceDirCount()
uint8_t(*)(void *userData, int chunkX, int chunkY, int chunkZ, int localX, int localY, int localZ) ChunkSampler
Optional out-of-chunk neighbor sampler for seam culling. Receives chunk coordinates plus the (possibl...
FaceDir
Six axis-aligned face directions. Each chunk keeps a separate instance buffer per direction so camera...
static PackedRect pack(int x, int y, int z, int width, int height, int tex)