Last active
September 27, 2025 00:00
-
-
Save Vercidium/a3002bd083cce2bc854c9ff8f0118d33 to your computer and use it in GitHub Desktop.
Revisions
-
Vercidium revised this gist
Feb 2, 2020 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,6 +1,6 @@ // Code ported from https://0fps.net/2012/06/30/meshing-in-a-minecraft-game/ // Note this implementation does not support different block types or block normals // The original author describes how to do this here: https://0fps.net/2012/07/07/meshing-minecraft-part-2/ -
Vercidium revised this gist
Aug 4, 2019 . 1 changed file with 2 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -38,8 +38,8 @@ public void GreedyMesh() // q determines the direction (X, Y or Z) that we are searching // m.IsBlockAt(x,y,z) takes global map positions and returns true if a block exists there bool blockCurrent = 0 <= x[d] ? IsBlockAt(x[0] + chunkPosX, x[1] + chunkPosY, x[2] + chunkPosZ) : true; bool blockCompare = x[d] < CHUNK_SIZE - 1 ? IsBlockAt(x[0] + q[0] + chunkPosX, x[1] + q[1] + chunkPosY, x[2] + q[2] + chunkPosZ) : true; // The mask is set to true if there is a visible face between two blocks, // i.e. both aren't empty and both aren't blocks -
Vercidium revised this gist
Aug 4, 2019 . 1 changed file with 3 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -3,9 +3,11 @@ // Note this implemenetation does not support different block types or block normals // The original author describes how to do this here: https://0fps.net/2012/07/07/meshing-minecraft-part-2/ const int CHUNK_SIZE = 32; // These variables 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; -
Vercidium revised this gist
Aug 4, 2019 . 1 changed file with 7 additions and 7 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,5 +1,8 @@ // Code ported from https://0fps.net/2012/06/30/meshing-in-a-minecraft-game/ // Note this implemenetation does not support different block types or block normals // The original author describes how to do this here: https://0fps.net/2012/07/07/meshing-minecraft-part-2/ 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) @@ -29,18 +32,15 @@ public void GreedyMesh() for (x[v] = 0; x[v] < CHUNK_SIZE; ++x[v]) { for (x[u] = 0; x[u] < CHUNK_SIZE; ++x[u]) { // q determines the direction (X, Y or Z) that we are searching // m.IsBlockAt(x,y,z) takes global map positions and returns true if a block exists there bool blockCurrent = 0 <= x[d] ? m.IsBlockAt(x[0] + chunkPosX, x[1] + chunkPosY, x[2] + chunkPosZ) : true; bool blockCompare = x[d] < CHUNK_SIZE - 1 ? m.IsBlockAt(x[0] + q[0] + chunkPosX, x[1] + q[1] + chunkPosY, x[2] + q[2] + chunkPosZ) : true; // The mask is set to true if there is a visible face between two blocks, // i.e. both aren't empty and both aren't blocks mask[n++] = blockCurrent != blockCompare; } } @@ -50,7 +50,7 @@ public void GreedyMesh() n = 0; // Generate a mesh from the mask using lexicographic ordering, // by looping over each block in this slice of the chunk for (j = 0; j < CHUNK_SIZE; ++j) { for (i = 0; i < CHUNK_SIZE;) -
Vercidium revised this gist
Aug 4, 2019 . 1 changed file with 10 additions and 11 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -49,31 +49,30 @@ public void GreedyMesh() n = 0; // Generate a mesh from the mask using lexicographic ordering, // by looping over each block in this slice of the chunk 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 // This is done by searching along the current axis until mask[n + w] is false for (w = 1; i + w < CHUNK_SIZE && mask[n + w]; w++) { } // Compute the height of this quad and store it in h // This is done by checking if every block next to this row (range 0 to w) is also part of the mask. // For example, if w is 5 we currently have a quad of dimensions 1 x 5. To reduce triangle count, // greedy meshing will attempt to expand this quad out to CHUNK_SIZE x 5, but will stop if it reaches a hole in the mask var done = false; for (h = 1; j + h < CHUNK_SIZE; h++) { // Check each block next to this quad for (k = 0; k < w; ++k) { // If there's a hole in the mask, exit if (!mask[n + k + h * CHUNK_SIZE]) { done = true; -
Vercidium revised this gist
Aug 4, 2019 . 1 changed file with 14 additions and 3 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -21,6 +21,7 @@ public void GreedyMesh() var mask = new bool[CHUNK_SIZE * CHUNK_SIZE]; q[d] = 1; // Check each slice of the chunk one at a time for (x[d] = -1; x[d] < CHUNK_SIZE;) { // Compute the mask @@ -46,18 +47,28 @@ public void GreedyMesh() ++x[d]; n = 0; // Generate a mesh from the mask using lexicographic ordering by // looping over each block in this slice of the chunk 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 // This is done by searching along the current axis until mask[n + w] is false for (w = 1; i + w < CHUNK_SIZE && mask[n + w]; w++) { } // Compute the height of this quad and store it in h // This is done by checking if every block next to this row (range 0 to w) is also part of the mask. // For example, if w is 5, we currently have a quad of dimensions 1x5. // In this loop, we attempt to expand this quad out to 32x5, but stop // if we reach a hole in the mesh var done = false; for (h = 1; j + h < CHUNK_SIZE; h++) { @@ -77,7 +88,7 @@ public void GreedyMesh() x[u] = i; x[v] = j; // du and dv determine the size and orientation of this face var du = new int[3]; du[u] = w; @@ -91,7 +102,7 @@ public void GreedyMesh() new Int3(x[0] + du[0] + dv[0], x[1] + du[1] + dv[1], x[2] + du[2] + dv[2]) // Bottom right vertice position ); // Clear this part of the mask, so we don't add duplicate faces for (l = 0; l < h; ++l) for (k = 0; k < w; ++k) mask[n + k + l * CHUNK_SIZE] = false; -
Vercidium revised this gist
Aug 4, 2019 . 1 changed file with 11 additions and 10 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -23,29 +23,30 @@ public void GreedyMesh() for (x[d] = -1; x[d] < CHUNK_SIZE;) { // Compute the 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 original author describes how to do this here: https://0fps.net/2012/07/07/meshing-minecraft-part-2/ // q determines the direction (X, Y or Z) that we are searching // m.IsBlockAt(x,y,z) takes global map positions and returns true if a block exists there bool blockCurrent = 0 <= x[d] ? m.IsBlockAt(x[0] + chunkPosX, x[1] + chunkPosY, x[2] + chunkPosZ) : true; bool blockCompare = x[d] < CHUNK_SIZE - 1 ? m.IsBlockAt(x[0] + q[0] + chunkPosX, x[1] + q[1] + chunkPosY, x[2] + q[2] + chunkPosZ) : true; // The mask is set to true if there is a visible face between two blocks // i.e. both aren't empty and both aren't blocks mask[n++] = blockCurrent != blockCompare; } } ++x[d]; // Generate a mesh from the mask using lexicographic ordering n = 0; for (j = 0; j < CHUNK_SIZE; ++j) { @@ -56,7 +57,7 @@ public void GreedyMesh() // Compute the width of this quad and store it in w for (w = 1; i + w < CHUNK_SIZE && mask[n + w]; w++) { } // Compute the height of this quad and store it in h var done = false; for (h = 1; j + h < CHUNK_SIZE; h++) { @@ -95,7 +96,7 @@ public void GreedyMesh() for (k = 0; k < w; ++k) mask[n + k + l * CHUNK_SIZE] = false; // Increment counters and continue i += w; n += w; } -
Vercidium renamed this gist
Aug 4, 2019 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -36,7 +36,7 @@ public void GreedyMesh() // 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; -
Vercidium revised this gist
Aug 4, 2019 . 1 changed file with 20 additions and 12 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,5 +1,12 @@ // 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) @@ -11,25 +18,26 @@ public void GreedyMesh() 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; } @@ -39,22 +47,22 @@ public void GreedyMesh() // 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; @@ -75,7 +83,7 @@ public void GreedyMesh() 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 @@ -85,7 +93,7 @@ public void GreedyMesh() // 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; -
Vercidium created this gist
Aug 4, 2019 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,103 @@ // Code ported from https://0fps.net/2012/06/30/meshing-in-a-minecraft-game/ 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[Constants.ChunkSize * Constants.ChunkSize]; q[d] = 1; for (x[d] = -1; x[d] < Constants.ChunkSize;) { // Compute mask var n = 0; for (x[v] = 0; x[v] < Constants.ChunkSize; ++x[v]) { for (x[u] = 0; x[u] < Constants.ChunkSize; ++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 bool blockEmpty = 0 <= x[d] ? m.IsBlockAt(x[0] + chunkPosX, x[1] + chunkPosY, x[2] + chunkPosZ) : true; bool blockCovered = x[d] < Constants.ChunkSize - 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 < Constants.ChunkSize; ++j) { for (i = 0; i < Constants.ChunkSize;) { if (mask[n]) { // Compute the width of this quad and store it in w for (w = 1; i + w < Constants.ChunkSize && mask[n + w]; w++) { } // Compute height of this quad and store it in h var done = false; for (h = 1; j + h < Constants.ChunkSize; h++) { for (k = 0; k < w; ++k) { if (!mask[n + k + h * Constants.ChunkSize]) { 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. No colour, normal or texture is 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 * Constants.ChunkSize] = false; //Increment counters and continue i += w; n += w; } else { i++; n++; } } } } } }