Biome mixing tweaks to texture util
This commit is contained in:
parent
d14b267cfd
commit
0dbb3b2844
@ -468,20 +468,18 @@ public class HeightMapMCAGenerator extends MCAWriter implements Extent {
|
|||||||
int widthIndex = img.getWidth() - 1;
|
int widthIndex = img.getWidth() - 1;
|
||||||
int heightIndex = img.getHeight() - 1;
|
int heightIndex = img.getHeight() - 1;
|
||||||
int maxIndex = biomes.length - 1;
|
int maxIndex = biomes.length - 1;
|
||||||
|
|
||||||
|
int[] buffer = new int[2];
|
||||||
for (int y = 0; y < img.getHeight(); y++) {
|
for (int y = 0; y < img.getHeight(); y++) {
|
||||||
boolean yBiome = y > 0 && y < heightIndex;
|
boolean yBiome = y > 0 && y < heightIndex;
|
||||||
for (int x = 0; x < img.getWidth(); x++) {
|
for (int x = 0; x < img.getWidth(); x++, index++) {
|
||||||
int color = img.getRGB(x, y);
|
int color = img.getRGB(x, y);
|
||||||
BaseBlock block = textureUtil.getNearestBlock(color);
|
if (textureUtil.getIsBlockCloserThanBiome(buffer, color, biomePriority)) {
|
||||||
TextureUtil.BiomeColor biome = textureUtil.getNearestBiome(color);
|
char combined = (char) buffer[0];
|
||||||
int blockColor = textureUtil.getColor(block);
|
|
||||||
biomes[index] = (byte) biome.id;
|
|
||||||
if (textureUtil.colorDistance(biome.grass, color) - biomePriority > textureUtil.colorDistance(blockColor, color)) {
|
|
||||||
char combined = (char) block.getCombined();
|
|
||||||
main[index] = combined;
|
main[index] = combined;
|
||||||
floor[index] = combined;
|
floor[index] = combined;
|
||||||
}
|
}
|
||||||
index++;
|
biomes[index] = (byte) buffer[1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -118,4 +118,4 @@ public class CopyPastaBrush implements Brush, ResettableTool {
|
|||||||
editSession.flushQueue();
|
editSession.flushQueue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -49,6 +49,16 @@ public class DelegateTextureUtil extends TextureUtil {
|
|||||||
return parent.getColor(block);
|
return parent.getColor(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getIsBlockCloserThanBiome(int[] blockAndBiomeIdOutput, int color, int biomePriority) {
|
||||||
|
return parent.getIsBlockCloserThanBiome(blockAndBiomeIdOutput, color, biomePriority);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getBiomeMix(int[] biomeIdsOutput, int color) {
|
||||||
|
return parent.getBiomeMix(biomeIdsOutput, color);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BiomeColor getBiome(int biome) {
|
public BiomeColor getBiome(int biome) {
|
||||||
return parent.getBiome(biome);
|
return parent.getBiome(biome);
|
||||||
|
@ -16,8 +16,10 @@ public class RandomTextureUtil extends CachedTextureUtil {
|
|||||||
this.grassColor = parent.getColor(FaweCache.getBlock(BlockID.GRASS, 0));
|
this.grassColor = parent.getColor(FaweCache.getBlock(BlockID.GRASS, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int index;
|
||||||
|
private int[] biomeMixBuffer = new int[3];
|
||||||
private Int2ObjectOpenHashMap<Integer> offsets = new Int2ObjectOpenHashMap<>();
|
private Int2ObjectOpenHashMap<Integer> offsets = new Int2ObjectOpenHashMap<>();
|
||||||
private Int2ObjectOpenHashMap<Integer> biomeOffsets = new Int2ObjectOpenHashMap<>();
|
private Int2ObjectOpenHashMap<int[]> biomeMixes = new Int2ObjectOpenHashMap<>();
|
||||||
|
|
||||||
protected int addRandomColor(int c1, int c2) {
|
protected int addRandomColor(int c1, int c2) {
|
||||||
int red1 = (c1 >> 16) & 0xFF;
|
int red1 = (c1 >> 16) & 0xFF;
|
||||||
@ -38,26 +40,45 @@ public class RandomTextureUtil extends CachedTextureUtil {
|
|||||||
} else {
|
} else {
|
||||||
return PseudoRandom.random.nextInt(i);
|
return PseudoRandom.random.nextInt(i);
|
||||||
}
|
}
|
||||||
// return i;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getIsBlockCloserThanBiome(int[] blockAndBiomeIdOutput, int color, int biomePriority) {
|
||||||
|
BaseBlock block = getNearestBlock(color);
|
||||||
|
int[] mix = biomeMixes.getOrDefault(color, null);
|
||||||
|
if (mix == null) {
|
||||||
|
int average = getBiomeMix(biomeMixBuffer, color);
|
||||||
|
mix = new int[4];
|
||||||
|
System.arraycopy(biomeMixBuffer, 0, mix, 0, 3);
|
||||||
|
mix[3] = average;
|
||||||
|
biomeMixes.put(color, mix);
|
||||||
|
}
|
||||||
|
if (++index > 2) index = 0;
|
||||||
|
int biomeId = mix[index];
|
||||||
|
int biomeAvColor = mix[3];
|
||||||
|
int blockColor = getColor(block);
|
||||||
|
blockAndBiomeIdOutput[0] = block.getCombined();
|
||||||
|
blockAndBiomeIdOutput[1] = biomeId;
|
||||||
|
if (colorDistance(biomeAvColor, color) - biomePriority > colorDistance(blockColor, color)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BiomeColor getNearestBiome(int color) {
|
public BiomeColor getNearestBiome(int color) {
|
||||||
int offsetColor = biomeOffsets.getOrDefault(color, 0);
|
int[] mix = biomeMixes.getOrDefault(color, null);
|
||||||
if (offsetColor != 0) {
|
if (mix == null) {
|
||||||
offsetColor = addRandomColor(color, offsetColor);
|
int average = getBiomeMix(biomeMixBuffer, color);
|
||||||
} else {
|
mix = new int[4];
|
||||||
offsetColor = color;
|
System.arraycopy(biomeMixBuffer, 0, mix, 0, 3);
|
||||||
|
mix[3] = average;
|
||||||
|
biomeMixes.put(color, mix);
|
||||||
}
|
}
|
||||||
BiomeColor res = super.getNearestBiome(offsetColor);
|
if (++index > 2) index = 0;
|
||||||
int newColor = res.grass;
|
int biomeId = mix[index];
|
||||||
{
|
return getBiome(biomeId);
|
||||||
byte dr = (byte) (((color >> 16) & 0xFF) - ((newColor >> 16) & 0xFF));
|
|
||||||
byte dg = (byte) (((color >> 8) & 0xFF) - ((newColor >> 8) & 0xFF));
|
|
||||||
byte db = (byte) (((color >> 0) & 0xFF) - ((newColor >> 0) & 0xFF));
|
|
||||||
biomeOffsets.put(color, (Integer) ((dr << 16) + (dg << 8) + (db << 0)));
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -11,6 +11,8 @@ import com.sk89q.worldedit.blocks.BlockID;
|
|||||||
import com.sk89q.worldedit.world.registry.BundledBlockData;
|
import com.sk89q.worldedit.world.registry.BundledBlockData;
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||||
|
import it.unimi.dsi.fastutil.ints.IntArraySet;
|
||||||
|
import it.unimi.dsi.fastutil.longs.LongArrayList;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
@ -50,9 +52,13 @@ public class TextureUtil {
|
|||||||
protected long[] distances;
|
protected long[] distances;
|
||||||
protected int[] validColors;
|
protected int[] validColors;
|
||||||
protected char[] validBlockIds;
|
protected char[] validBlockIds;
|
||||||
|
|
||||||
protected int[] validLayerColors;
|
protected int[] validLayerColors;
|
||||||
protected char[][] validLayerBlocks;
|
protected char[][] validLayerBlocks;
|
||||||
|
|
||||||
|
protected int[] validMixBiomeColors;
|
||||||
|
protected long[] validMixBiomeIds;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://github.com/erich666/Mineways/blob/master/Win/biomes.cpp
|
* https://github.com/erich666/Mineways/blob/master/Win/biomes.cpp
|
||||||
@ -420,6 +426,43 @@ public class TextureUtil {
|
|||||||
return biomes[biome];
|
return biomes[biome];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean getIsBlockCloserThanBiome(int[] blockAndBiomeIdOutput, int color, int biomePriority) {
|
||||||
|
BaseBlock block = getNearestBlock(color);
|
||||||
|
TextureUtil.BiomeColor biome = getNearestBiome(color);
|
||||||
|
int blockColor = getColor(block);
|
||||||
|
blockAndBiomeIdOutput[0] = block.getCombined();
|
||||||
|
blockAndBiomeIdOutput[1] = biome.id;
|
||||||
|
if (colorDistance(biome.grass, color) - biomePriority > colorDistance(blockColor, color)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBiomeMix(int[] biomeIdsOutput, int color) {
|
||||||
|
long closest = Long.MAX_VALUE;
|
||||||
|
int closestAverage = Integer.MAX_VALUE;
|
||||||
|
long min = Long.MAX_VALUE;
|
||||||
|
int red1 = (color >> 16) & 0xFF;
|
||||||
|
int green1 = (color >> 8) & 0xFF;
|
||||||
|
int blue1 = (color >> 0) & 0xFF;
|
||||||
|
int alpha = (color >> 24) & 0xFF;
|
||||||
|
for (int i = 0; i < validMixBiomeColors.length; i++) {
|
||||||
|
int other = validMixBiomeColors[i];
|
||||||
|
if (((other >> 24) & 0xFF) == alpha) {
|
||||||
|
long distance = colorDistance(red1, green1, blue1, other);
|
||||||
|
if (distance < min) {
|
||||||
|
min = distance;
|
||||||
|
closest = validMixBiomeIds[i];
|
||||||
|
closestAverage = other;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
biomeIdsOutput[0] = (int) ((closest >> 0) & 0xFF);
|
||||||
|
biomeIdsOutput[1] = (int) ((closest >> 8) & 0xFF);
|
||||||
|
biomeIdsOutput[2] = (int) ((closest >> 16) & 0xFF);
|
||||||
|
return closestAverage;
|
||||||
|
}
|
||||||
|
|
||||||
public BiomeColor getNearestBiome(int color) {
|
public BiomeColor getNearestBiome(int color) {
|
||||||
int grass = blockColors[2 << 4];
|
int grass = blockColors[2 << 4];
|
||||||
if (grass == 0) {
|
if (grass == 0) {
|
||||||
@ -633,12 +676,47 @@ public class TextureUtil {
|
|||||||
List<BiomeColor> valid = new ArrayList<>();
|
List<BiomeColor> valid = new ArrayList<>();
|
||||||
for (int i = 0; i < biomes.length; i++) {
|
for (int i = 0; i < biomes.length; i++) {
|
||||||
BiomeColor biome = biomes[i];
|
BiomeColor biome = biomes[i];
|
||||||
biome.grass = multiplyColor(biome.grass, grass);
|
// biome.grass = multiplyColor(biome.grass, grass);
|
||||||
if (biome.grass != 0 && !biome.name.equalsIgnoreCase("Unknown Biome")) {
|
if (biome.grass != 0 && !biome.name.equalsIgnoreCase("Unknown Biome")) {
|
||||||
valid.add(biome);
|
valid.add(biome);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.validBiomes = valid.toArray(new BiomeColor[valid.size()]);
|
this.validBiomes = valid.toArray(new BiomeColor[valid.size()]);
|
||||||
|
|
||||||
|
{
|
||||||
|
ArrayList<BiomeColor> uniqueColors = new ArrayList<>();
|
||||||
|
Set<Integer> uniqueBiomesColors = new IntArraySet();
|
||||||
|
for (BiomeColor color : validBiomes) {
|
||||||
|
if (uniqueBiomesColors.add(color.grass)) {
|
||||||
|
uniqueColors.add(color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int count = 0;
|
||||||
|
int count2 = 0;
|
||||||
|
uniqueBiomesColors.clear();
|
||||||
|
|
||||||
|
LongArrayList layerIds = new LongArrayList();
|
||||||
|
LongArrayList layerColors = new LongArrayList();
|
||||||
|
for (int i = 0; i < uniqueColors.size(); i++) {
|
||||||
|
for (int j = i; j < uniqueColors.size(); j++) {
|
||||||
|
for (int k = j; k < uniqueColors.size(); k++) {
|
||||||
|
BiomeColor c1 = uniqueColors.get(i);
|
||||||
|
BiomeColor c2 = uniqueColors.get(j);
|
||||||
|
BiomeColor c3 = uniqueColors.get(k);
|
||||||
|
int average = averageColor(c1.grass, c2.grass, c3.grass);
|
||||||
|
if (uniqueBiomesColors.add(average)) {
|
||||||
|
count++;
|
||||||
|
layerColors.add((long) average);
|
||||||
|
layerIds.add((long) ((c1.id) + (c2.id << 8) + (c3.id << 16)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
validMixBiomeColors = new int[layerColors.size()];
|
||||||
|
for (int i = 0; i < layerColors.size(); i++) validMixBiomeColors[i] = (int) layerColors.getLong(i);
|
||||||
|
validMixBiomeIds = layerIds.toLongArray();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -703,6 +781,25 @@ public class TextureUtil {
|
|||||||
return (alpha << 24) + (red << 16) + (green << 8) + (blue << 0);
|
return (alpha << 24) + (red << 16) + (green << 8) + (blue << 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int averageColor(int... colors) {
|
||||||
|
int alpha = 0;
|
||||||
|
int red = 0;
|
||||||
|
int green = 0;
|
||||||
|
int blue = 0;
|
||||||
|
for (int c : colors) {
|
||||||
|
alpha += (c >> 24) & 0xFF;
|
||||||
|
red += (c >> 16) & 0xFF;
|
||||||
|
green += (c >> 8) & 0xFF;
|
||||||
|
blue += (c >> 0) & 0xFF;
|
||||||
|
}
|
||||||
|
int num = colors.length;
|
||||||
|
alpha /= num;
|
||||||
|
red /= num;
|
||||||
|
green /= num;
|
||||||
|
blue /= num;
|
||||||
|
return (alpha << 24) + (red << 16) + (green << 8) + (blue << 0);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assumes the top layer is a transparent color and the bottom is opaque
|
* Assumes the top layer is a transparent color and the bottom is opaque
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user