Guest User

Greedy meshing - C++

a guest
Aug 4th, 2014
56
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