Advertisement
Guest User

Untitled

a guest
Apr 22nd, 2016
108
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 4.36 KB | None | 0 0
  1.  
  2.     /**
  3.      * Returns pair of min and max height values for skylight update, or null for no update.
  4.      *
  5.      * Getting light Y update bounds when generating cubes isn't as trivial as it may seem to be.
  6.      *
  7.      * If there was some free space below that cube - it may need a skylight update.
  8.      * If there are only fully opaque blocks below (opacity >= 15) - nothing below was updated.
  9.      *
  10.      * So in this case here is what happens (2d example):
  11.      *
  12.      * ===
  13.      * ### - block
  14.      * ===
  15.      * ...
  16.      * ... - air
  17.      * ...
  18.      * ;;;
  19.      * ;;; - dark air
  20.      * ;;;
  21.      *
  22.      * x-1 x x+1
  23.      * ...===...
  24.      * ...###...
  25.      * ...===...
  26.      * ...;;;...
  27.      * ...;;;...
  28.      * ...;;;...
  29.      * ===;;;...
  30.      * ###;;;...
  31.      * ===;;;...
  32.      * =========
  33.      * #########
  34.      * =========
  35.      *
  36.      * In this case light should spread from lit areas from x-1 and x+1 to x
  37.      * and from above top block at x if it's semi-transparent.
  38.      * The minimum Y that light can directly spread to is at [min(heightAt(x-1), heightAt(x+1)) + 1]
  39.      * And the maximum Y that light can directly spread to is [heightAt(x) - 1].
  40.      * But it can also spread from above, so heightAt(x) also needs update.
  41.      * (assuming heightAt returns height of the top opaque block).
  42.      * When all surrounding heights are higher, light can't spread here, so nothing happens.
  43.      *
  44.      * We don't need to care about cases when light spreads to current block indirectly,
  45.      * It needs to spread to some other block directly for that to happen, and world.checkLightFor()
  46.      * recalculates full light spread.
  47.      *
  48.      * Note that world.checkLightFor() doesn't cause light to spread to/from (x, y, z) if light value
  49.      * in this block is already correct. It only updates if light value isn't equal to raw light value
  50.      * which is max of light at (x, y, z), and [light values from surrounding blocks - 1].
  51.      *
  52.      * In this state all non-lit blocks that may need update should have light values 0,
  53.      * so we need to care only about blocks light can spread to directly from surrounding blocks.
  54.      */
  55.     private Pair<Integer, Integer> getMinMaxLightUpdateY(ICubeCache cache, Cube cube, int blockX, int blockZ) {
  56.         //getHeightmapValue(x, y, z) = heightOfTopBlock+1
  57.         int heightMax = getHeightmapValue(cache, blockX, blockZ) - 1;//==Y of the top block
  58.  
  59.         int cubeY = cube.getY();
  60.         //if the top block is below current cube - this cube couldn't change anything
  61.         //because there are no opaque blocks
  62.         if (blockToCube(heightMax) < cubeY) {
  63.             return null;
  64.         }
  65.  
  66.         int heightmapZpos = getHeightmapValue(cache, blockX, blockZ + 1);
  67.         int heightmapZneg = getHeightmapValue(cache, blockX, blockZ - 1);
  68.         int heightmapXpos = getHeightmapValue(cache, blockX + 1, blockZ);
  69.         int heightmapXneg = getHeightmapValue(cache, blockX - 1, blockZ);
  70.  
  71.         //heightmap is already block above top block, don't add 1
  72.         int heightMin = min(heightmapZpos, heightmapZneg, heightmapXpos, heightmapXneg);
  73.  
  74.         //if the top block is above - the top block didn't change. Calculate light only in this cube
  75.         if(blockToCube(heightMax) > cubeY) {
  76.             if (heightMin > heightMax) {
  77.                 return null;
  78.             }
  79.             int cubeBottomY = cubeToMinBlock(cubeY);
  80.             int cubeTopY = cubeToMaxBlock(cubeY);
  81.             //if heightMin is also above that cube - no reason to update at all.
  82.             //It must be dark or light will get there from cube edge.
  83.             if(blockToCube(heightMin) > cube.getY()) {
  84.                 return null;
  85.             }
  86.             heightMin = Math.max(heightMin, cubeBottomY);
  87.             heightMax = Math.min(heightMax, cubeTopY);
  88.             assert heightMin <= heightMax : "heightMin > heightMax (" + heightMin + ">" + heightMax + ")";
  89.             return new ImmutablePair<>(heightMin, heightMax);
  90.         }
  91.  
  92.         int cubeBottomY = cubeToMinBlock(cubeY);
  93.         //add one to get block just above
  94.         int heightBelowCube = getHeightmapBelowCubeY(
  95.                 cube.getColumn(), blockToLocal(blockX), blockToLocal(blockZ), cubeY) + 1;
  96.         mutablePos.set(blockX, cubeBottomY, blockZ);
  97.  
  98.         assert heightBelowCube <= cubeBottomY : "heightBelowCube <= cubeBottomY (" + heightBelowCube + " > " + cubeBottomY + ")";
  99.         boolean isBlockBelowCubeBottomOpaque = heightBelowCube == cubeBottomY;
  100.  
  101.         if(!isBlockBelowCubeBottomOpaque) {
  102.             //extend skylight refresh to the top block below current cube
  103.             //it needs relight because it's set to full darkness, and light may reach it from somewhere else
  104.             heightMin = heightBelowCube;
  105.         }
  106.  
  107.         if (heightMin > heightMax) {
  108.             return null;
  109.         }
  110.         return new ImmutablePair<>(heightMin, heightMax);
  111.     }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement