/* Copyright (c) 2014 Jesper Öqvist <jesper@llbit.se>
*
* This file is part of Chunky.
*
* Chunky is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Chunky is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with Chunky. If not, see <http://www.gnu.org/licenses/>.
*/
package se.llbit.chunky.map;
import se.llbit.chunky.world.Block;
import se.llbit.chunky.world.Chunk;
import se.llbit.math.ColorUtil;
import se.llbit.math.QuickMath;
public class CaveLayer extends BitmapLayer {
private final byte[] caves;
private final int avgColor;
/**
* Generate the cave map. Only holes which are large enough to have mobs spawn
* in them are counted towards the color of a cave. The color is then determined
* by the number of unoccupied blocks beneath the topmost (surface) block.
*
* <p>The more empty space, the deeper the cave color.
*/
public CaveLayer(byte[] blocksArray, int[] heightmap) {
caves = new byte[Chunk.X_MAX * Chunk.Z_MAX];
int luft = 0;
for (int x = 0; x < Chunk.X_MAX; ++x) {
for (int z = 0; z < Chunk.Z_MAX; ++z) {
int y = heightmap[z * 16 + x];
y = Math.max(0, y - 1);
// Find ground level.
for (; y > 1; --y) {
int block = blocksArray[Chunk.chunkIndex(x, y, z)] & 0xFF;
if (Block.get(block).isGroundBlock()) {
break;
}
}
// find caves
int luftspalt = 0;
for (; y > 1; --y) {
Block block = Block.get(blocksArray[Chunk.chunkIndex(x, y, z)]);
if (block.isCave()) {
y -= 1;
Block block1 = Block.get(blocksArray[Chunk.chunkIndex(x, y, z)]);
if (block1.isCave()) {
luftspalt++;
y -= 1;
}
}
}
luftspalt = (luftspalt < 64) ? luftspalt : 64;
caves[x * Chunk.Z_MAX + z] = (byte) luftspalt;
luft += luftspalt;
}
}
avgColor = color((byte) (luft / (float) (Chunk.X_MAX * Chunk.Z_MAX)));
}
@Override public int colorAt(int x, int z) {
return color(caves[x * 16 + z]);
}
private int color(byte luftspalt) {
if (luftspalt == 0) {
return 0xFFFFFFFF;
} else {
double fade = QuickMath.min(1, (luftspalt * 3 + 5) / 64.0);
return ColorUtil.getRGB(1.0 - fade, 1.0 - fade, 1.0);
}
}
@Override public int getAvgColor() {
return avgColor;
}
}