SHARE
TWEET

Greedy meshing - C++

a guest Aug 4th, 2014 41 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // in the snippet following variables will be needed:
  2. // chunkSizeX/Y/Z - the size of one chunk in the x/y/z-direction
  3. // sectionHeight - the height of one section inside a chunk, e.g.: sectionHeight = 16 and chunkSizeY=256 makes 16 sections
  4. // currentChunk - reference to a Chunk structure
  5.  
  6.  
  7. enum Face
  8. {
  9.         North   = 1,
  10.         East    = 2,
  11.         South   = 4,
  12.         West    = 8,
  13.         Top     = 16,
  14.         Bottom  = 32
  15. };
  16.  
  17. struct Block
  18. {
  19.         int Type;
  20.         Face VisibleFaces;
  21. };
  22.  
  23. struct Chunk
  24. {
  25.         float x, y, z;
  26.         Block blockData[];
  27. };
  28.  
  29.  
  30. int numBlocksPerSection = chunkSizeX * sectionHeight * chunkSizeZ;
  31. bool handled[] = new bool[numBlocksPerSection];
  32. Face activeFace = (Face)1;
  33.  
  34. // iterate over all 6 faces
  35. for (int f = 0; f < 6; ++f)
  36. {
  37.         // reset all blocks not to be handled
  38.         memset(handled, FALSE, numBlocksPerSection);
  39.  
  40.         for(int x = 0; x < chunkSizeX; ++x)
  41.         {
  42.                 for(int y = 0; y < sectionHeight; ++y)
  43.                 {
  44.                         for(int z = 0; z < chunkSizeZ; ++z)
  45.                         {
  46.                                 // global and relative indices
  47.                                 int iGlobal = x + chunkSizeX * ((y + currentSection * sectionHeight) + chunkSizeY * z);
  48.                                 int iRelative = x + chunkSizeX * (y + sectionHeight * z);
  49.  
  50.                                 Face faces = currentChunk.blockData[iGlobal].VisibleFaces;
  51.  
  52.                                 // continue if face is not visible or was handled already
  53.                                 if(!(faces & activeFace) || handled[iRelative])
  54.                                 {
  55.                                         handled[iRelative] = true;
  56.                                         continue;
  57.                                 }
  58.  
  59.                                 int width = 1, height = 1, depth = 1;
  60.  
  61.                                 // skip width check if activeFace is East or West -> no width
  62.                                 if(!(activeFace & East || activeFace & West))
  63.                                 {
  64.                                         // calculate width for same faces being adjacent to current block
  65.                                         for(; width < chunkSizeX - x &&
  66.                                                 currentChunk.blockData[SHIFT_INDEX_X(iGlobal, width)].VisibleFaces & tmp &&
  67.                                                 currentChunk.blockData[iGlobal].Type == currentChunk.blockData[SHIFT_INDEX_X(iGlobal, width)].Type &&
  68.                                                 && !handled[SHIFT_SECTIONINDEX_X(iRelative, width)]; ++width);
  69.                                 }
  70.  
  71.                                 bool done = false;
  72.  
  73.                                 // skip depth check if activeFace is North or South -> no depth
  74.                                 if(!(activeFace & North || activeFace & South))
  75.                                 {
  76.                                         // calculate depth for same faces being adjacent to current block
  77.                                         for(; depth < chunkSizeZ - z; ++depth)
  78.                                         {
  79.                                                 // this time add another loop, to make sure, only increment depth if all blocks inside the width range are same
  80.                                                 for(int u = 0; u < width; ++u)
  81.                                                 {
  82.                                                         int indexGlobal = SHIFT_INDEX_X(SHIFT_INDEX_Z(iGlobal, depth), u);
  83.                                                         int indexRelative = SHIFT_RELATIVEINDEX_X(SHIFT_RELATIVEINDEX_Z(iRelative, depth), u);
  84.                                                         if(!(currentChunk.blockData[indexGlobal].VisibleFaces & activeFace &&
  85.                                                                 currentChunk.blockData[iGlobal].Type == currentChunk.blockData[indexGlobal].Type) ||
  86.                                                                 handled[indexRelative])
  87.                                                         {
  88.                                                                 done = true;
  89.                                                                 break;
  90.                                                         }
  91.                                                 }
  92.                                                 if(done)
  93.                                                         break;
  94.                                         }
  95.                                 }
  96.  
  97.                                 done = false;
  98.  
  99.                                 // skip height check if activeFace is Top or Bottom -> no height
  100.                                 if(!(activeFace & Top || activeFace & Bottom))
  101.                                 {
  102.                                         // calculate height
  103.                                         for(; height < sectionHeight - y; ++height)
  104.                                         {
  105.                                                 // add loops for width and depth
  106.                                                 for(int u = 0; u < width; ++u)
  107.                                                 {
  108.                                                         for(int v = 0; v < depth; ++v)
  109.                                                         {
  110.                                                                 int indexGlobal = SHIFT_INDEX_X(SHIFT_INDEX_Y(SHIFT_INDEX_Z(iGlobal, v), height), u);
  111.                                                                 int indexRelative = SHIFT_RELATIVEINDEX_X(SHIFT_RELATIVEINDEX_Y(SHIFT_RELATIVEINDEX_Z(iRelative, v), height), u);
  112.                                                                 if(!(currentChunk.blockData[indexGlobal].VisibleFaces & activeFace ||
  113.                                                                         currentChunk.blockData[iGlobal].Type == currentChunk.blockData[indexGlobal].Type) ||
  114.                                                                         handled[indexRelative])
  115.                                                                 {
  116.                                                                         done = true;
  117.                                                                         break;
  118.                                                                 }
  119.                                                         }
  120.                                                         if(done)        break;
  121.                                                 }
  122.                                                 if(done)        break;
  123.                                         }
  124.                                 }
  125.  
  126.                                 // make sure we add the calculated face range to the handled array
  127.                                 for(int a = 0; a < width; ++a)
  128.                                         for(int b = 0; b < height; ++b)
  129.                                                 for(int c = 0; c < depth; ++c)
  130.                                                         handled[SHIFT_RELATIVEINDEX_X(SHIFT_RELATIVEINDEX_Y(SHIFT_RELATIVEINDEX_Z(iRelative, c), b), a)] = true;
  131.  
  132.                                 // add the quad's vertices here, dependent on the activeFace,
  133.                                 // e.g. for North and a counter-clockwise ordering:
  134.                                 // position1 = vector3(width + x + currentChunk.x, y + currentChunk.y, depth + z + currentChunk.z);
  135.                                 // position2 = vector3(width + x + currentChunk.x, y + height + currentChunk.y, depth + z + currentChunk.z);
  136.                                 // position3 = vector3(x + currentChunk.x, y + height + currentChunk.y, depth + z + currentChunk.z);
  137.                                 // position4 = vector3(x + currentChunk.x, y + currentChunk.y, depth + z + currentChunk.z);
  138.                         }
  139.                 }
  140.         }
  141.  
  142.         activeFace = (Face)(activeFace * 2);           
  143. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Top