// Code ported from https://0fps.net/2012/06/30/meshing-in-a-minecraft-game/ const int CHUNK_SIZE = 32; // These store the location of the chunk in the world, e.g. (0,0,0), (32,0,0), (64,0,0) int chunkPosX = 0; int chunkPosY = 0; int chunkPosZ = 0; public void GreedyMesh() { // Sweep over each axis (X, Y and Z) for (var d = 0; d < 3; ++d) { int i, j, k, l, w, h; int u = (d + 1) % 3; int v = (d + 2) % 3; var x = new int[3]; var q = new int[3]; var mask = new bool[CHUNK_SIZE * CHUNK_SIZE]; q[d] = 1; for (x[d] = -1; x[d] < CHUNK_SIZE;) { // Compute mask var n = 0; for (x[v] = 0; x[v] < CHUNK_SIZE; ++x[v]) { for (x[u] = 0; x[u] < CHUNK_SIZE; ++x[u]) { // Note this implemenetation does not support different block types or block normals // The mask is set to true if there is a visible face between two blocks. // q determines the direction that we are searching // m.IsBlockAt(x,y,z) takes global map positions and returns true if a block exists there // chunkPosX, chunkPosY and chunkPosZ store the location of this chunk in the world bool blockEmpty = 0 <= x[d] ? m.IsBlockAt(x[0] + chunkPosX, x[1] + chunkPosY, x[2] + chunkPosZ) : true; bool blockCovered = x[d] < CHUNK_SIZE - 1 ? m.IsBlockAt(x[0] + q[0] + chunkPosX, x[1] + q[1] + chunkPosY, x[2] + q[2] + chunkPosZ) : true; mask[n++] = blockEmpty != blockCovered; } } ++x[d]; // Generate mesh from the mask using lexicographic ordering n = 0; for (j = 0; j < CHUNK_SIZE; ++j) { for (i = 0; i < CHUNK_SIZE;) { if (mask[n]) { // Compute the width of this quad and store it in w for (w = 1; i + w < CHUNK_SIZE && mask[n + w]; w++) { } // Compute height of this quad and store it in h var done = false; for (h = 1; j + h < CHUNK_SIZE; h++) { for (k = 0; k < w; ++k) { if (!mask[n + k + h * CHUNK_SIZE]) { done = true; break; } } if (done) break; } x[u] = i; x[v] = j; // du and dv determine the size and orientation of the face var du = new int[3]; du[u] = w; var dv = new int[3]; dv[v] = h; // Create a quad for this face. Colour, normal or textures are not stored in this block vertex format. BlockVertex.AppendQuad(new Int3(x[0], x[1], x[2]), // Top-left vertice position new Int3(x[0] + du[0], x[1] + du[1], x[2] + du[2]), // Top right vertice position new Int3(x[0] + dv[0], x[1] + dv[1], x[2] + dv[2]), // Bottom left vertice position new Int3(x[0] + du[0] + dv[0], x[1] + du[1] + dv[1], x[2] + du[2] + dv[2]) // Bottom right vertice position ); // Reset the mask for (l = 0; l < h; ++l) for (k = 0; k < w; ++k) mask[n + k + l * CHUNK_SIZE] = false; //Increment counters and continue i += w; n += w; } else { i++; n++; } } } } } }