/* Copyright (c) 2013-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.world; import org.apache.commons.math3.util.FastMath; import se.llbit.chunky.renderer.scene.Scene; import se.llbit.chunky.resources.BitmapImage; import se.llbit.math.ColorUtil; import se.llbit.math.QuickMath; /** * Biome constants and utility methods. * * @author Jesper Öqvist <jesper@llbit.se> */ public class Biomes { /** * Mask to get valid biome IDs (removes variant bit). * <p> * Currently we only handle 128 different biomes (40 currently implemented) * because biome IDs with the high bit set have the same properties, as far * as we are concerned, as the corresponding biome ID without the high bit. */ public static final int BIOME_MASK = 0x7F; private static final int SWAMP_ID = 6; private static final Biome unknown = new Biome("unknown", 0.5, 0.5, 0x7E7E7E, 0x7E7E7E); private static final Biome ocean = new Biome("ocean", 0.5, 0.5, 0x000070, 0x75B646); private static final Biome plains = new Biome("plains", 0.8, 0.4, 0x8DB360, 0x8DB84A); private static final Biome desert = new Biome("desert", 1.0, 0.0, 0xFA9418, 0x9BA863); private static final Biome extremeHills = new Biome("extreme hills", 0.2, 0.3, 0x606060, 0x75B646); private static final Biome forest = new Biome("forest", 0.7, 0.8, 0x056621, 0x4A8F3A); private static final Biome taiga = new Biome("taiga", 0.05, 0.8, 0x00DD2D, 0x478852); private static final Biome swampland = new Biome("swampland", 0.8, 0.9, 0x07F9B2, 0x3e5226); private static final Biome river = new Biome("river", 0.5, 0.5, 0x0000FF, 0x75B646); private static final Biome hell = new Biome("hell", 1.0, 0.0, 0xFF0000, 0x75B646); private static final Biome sky = new Biome("sky", 0.5, 0.5, 0x8080FF, 0x75B646); private static final Biome frozenOcean = new Biome("frozen ocean", 0.0, 0.5, 0x9090A0, 0x7A9C91); private static final Biome frozenRiver = new Biome("frozen river", 0.0, 0.5, 0xA0A0FF, 0x7A9C91); private static final Biome icePlains = new Biome("ice plains", 0.0, 0.5, 0xFFFFFF, 0x7A9C91); private static final Biome iceMountains = new Biome("ice mountains", 0.0, 0.5, 0xA0A0A0, 0x7A9C91); private static final Biome mushroomIsland = new Biome("mushroom island", 0.9, 1.0, 0xFF00FF, 0x939D88); private static final Biome mushroomIslandShore = new Biome("mushroom island shore", 0.9, 1.0, 0xA000FF, 0x939D88); private static final Biome beach = new Biome("beach", 0.8, 0.4, 0xFADE55, 0x75B646); private static final Biome desertHills = new Biome("desert hills", 1.0, 0.0, 0xD25F12, 0x9BA863); private static final Biome forestHills = new Biome("forest hills", 0.7, 0.8, 0x22551C, 0x4A8F3A); private static final Biome taigaHills = new Biome("taiga hills", 0.05, 0.8, 0x163933, 0x478852); private static final Biome extremeHillsEdge = new Biome("extreme hills edge", 0.2, 0.3, 0x72789A, 0x75B646); private static final Biome jungle = new Biome("jungle", 1.0, 0.9, 0x537B09, 0x3A8B25); private static final Biome jungleHills = new Biome("jungle hills", 1.0, 0.9, 0x2C4205, 0x3A8B25); private static final Biome jungleEdge = new Biome("jungle edge", 0.95, 0.8, 0x628B17, 0x3EB80F); private static final Biome deepOcean = new Biome("deep ocean", 0.5, 0.5, 0x000030, 0x71A74D); private static final Biome stoneBeach = new Biome("stone beach", 0.2, 0.3, 0xA2A284, 0x6DA36B); private static final Biome coldBeach = new Biome("cold beach", 0.05, 0.3, 0xFAF0C0, 0x64A278); private static final Biome birchForest = new Biome("birch forest", 0.7, 0.8, 0x307444, 0x59AE30); private static final Biome birchForestHills = new Biome("birch forest hills", 0.7, 0.8, 0x1F5F32, 0x59AE30); private static final Biome roofedForest = new Biome("roofed forest", 0.7, 0.8, 0x40511A, 0x59AE30); private static final Biome coldTaiga = new Biome("cold taiga", -0.5, 0.4, 0x31554A, 0x60A17B); private static final Biome coldTaigaHills = new Biome("cold taiga hills", -0.5, 0.4, 0x243F36, 0x60A17B); private static final Biome megaTaiga = new Biome("mega taiga", 0.3, 0.8, 0x596651, 0x68A55F); private static final Biome megaTaigaHills = new Biome("mega taiga hills", 0.3, 0.8, 0x454F3E, 0x68A55F); private static final Biome extremeHillsPlus = new Biome("extreme hills+", 0.2, 0.3, 0x507050, 0x6DA36B); private static final Biome savanna = new Biome("savanna", 1.2, 0.0, 0xBDB25F, 0xAEA42A); private static final Biome savannaPlateau = new Biome("savanna plateau", 1.0, 0.0, 0xA79D64, 0xAEA42A); private static final Biome mesa = new Biome("mesa", 2.0, 0.0, 0xD94515, 0xAEA42A); private static final Biome mesaPlateauF = new Biome("mesa plateau f", 2.0, 0.0, 0xB09765, 0xAEA42A); private static final Biome mesaPlateau = new Biome("mesa plateau", 2.0, 0.0, 0xCA8C65, 0xAEA42A); private static final Biome biomes[] = {ocean, plains, desert, extremeHills, forest, taiga, swampland, river, hell, sky, frozenOcean, frozenRiver, icePlains, iceMountains, mushroomIsland, mushroomIslandShore, beach, desertHills, forestHills, taigaHills, extremeHillsEdge, jungle, jungleHills, jungleEdge, deepOcean, stoneBeach, coldBeach, birchForest, birchForestHills, roofedForest, coldTaiga, coldTaigaHills, megaTaiga, megaTaigaHills, extremeHillsPlus, savanna, savannaPlateau, mesa, mesaPlateauF, mesaPlateau, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown}; private static int[] grassColor = new int[128]; private static int[] foliageColor = new int[128]; private static float[][] grassColorLinear = new float[grassColor.length][3]; private static float[][] foliageColorLinear = new float[grassColor.length][3]; static { for (int i = 0; i < biomes.length; ++i) { grassColor[i] = biomes[i].grassColor; foliageColor[i] = grassColor[i]; } gammaCorrectColors(grassColor, grassColorLinear); gammaCorrectColors(foliageColor, foliageColorLinear); } /** * @return Biome color for given biome ID */ public static int getColor(int biomeId) { return biomes[BIOME_MASK & biomeId].mapColor; } /** * Loads grass colors from a grass color texture. */ public static void loadGrassColors(BitmapImage texture) { loadColorsFromTexture(grassColor, texture); gammaCorrectColors(grassColor, grassColorLinear); } /** * Loads foliage colors from a grass color texture. */ public static void loadFoliageColors(BitmapImage texture) { loadColorsFromTexture(foliageColor, texture); gammaCorrectColors(foliageColor, foliageColorLinear); } private static void loadColorsFromTexture(int[] dest, BitmapImage texture) { for (int i = 0; i < biomes.length; ++i) { double temp = QuickMath.clamp(biomes[i].temp, 0, 1); double rain = QuickMath.clamp(biomes[i].rain, 0, 1); rain *= temp; int color = texture.getPixel((int) ((1 - temp) * 255), (int) ((1 - rain) * 255)); dest[i] = color; } // Swamp get special treatment. dest[SWAMP_ID] = ((dest[SWAMP_ID] & 0xFEFEFE) + 0x4E0E4E) / 2; } private static void gammaCorrectColors(int[] src, float[][] dest) { float[] frgb = new float[3]; for (int i = 0; i < src.length; ++i) { ColorUtil.getRGBComponents(src[i], frgb); dest[i][0] = (float) FastMath.pow(frgb[0], Scene.DEFAULT_GAMMA); dest[i][1] = (float) FastMath.pow(frgb[1], Scene.DEFAULT_GAMMA); dest[i][2] = (float) FastMath.pow(frgb[2], Scene.DEFAULT_GAMMA); } } /** * @param biomeId truncated to [0,127] * @return Grass color for the given biome ID */ public static int getGrassColor(int biomeId) { return grassColor[BIOME_MASK & biomeId]; } /** * @param biomeId truncated to [0,127] * @return Foliage color for the given biome ID */ public static int getFoliageColor(int biomeId) { return foliageColor[BIOME_MASK & biomeId]; } /** * @param biomeId truncated to [0,127] * @return Linear biome color for the given biome ID */ public static float[] getGrassColorLinear(int biomeId) { return grassColorLinear[BIOME_MASK & biomeId]; } /** * @param biomeId truncated to [0,127] * @return Linear foliage color for the given biome ID */ public static float[] getFoliageColorLinear(int biomeId) { return foliageColorLinear[BIOME_MASK & biomeId]; } /** * @param biomeId truncated to [0,127] * @return Biome name */ public static String getName(int biomeId) { return biomes[BIOME_MASK & biomeId].name; } }