CFI with glass coloring

This commit is contained in:
Jesse Boyd 2017-04-28 08:37:54 +10:00
parent 370ce99d93
commit 01d8002a7f
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
4 changed files with 121 additions and 13 deletions

View File

@ -255,6 +255,24 @@ public class HeightMapMCAGenerator extends MCAWriter implements Extent {
}
}
public void setColorWithGlass(BufferedImage img) {
CachedTextureUtil textureUtil = new CachedTextureUtil(Fawe.get().getTextureUtil());
if (img.getWidth() != getWidth() || img.getHeight() != getLength())
throw new IllegalArgumentException("Input image dimensions do not match the current height map!");
int index = 0;
for (int y = 0; y < img.getHeight(); y++) {
for (int x = 0; x < img.getWidth(); x++) {
int color = img.getRGB(x, y);
char[] layer = textureUtil.getNearestLayer(color);
if (layer == null) {
continue;
}
floor[index] = layer[0];
main[index++] = layer[1];
}
}
}
public void setBiome(Mask mask, byte biome) {
int index = 0;
for (int z = 0; z < getLength(); z++) {

View File

@ -162,12 +162,12 @@ public class CreateFromImage extends Command {
return;
}
if (argList.size() == 1) {
if (StringMan.isEqualIgnoreCaseToAny(argList.get(0), "setbiome", "setoverlay", "setmain", "setfloor", "setcolumn", "setcolor")) {
if (StringMan.isEqualIgnoreCaseToAny(argList.get(0), "setbiome", "setoverlay", "setmain", "setfloor", "setcolumn", "setcolor", "setglasscolor")) {
C.COMMAND_SYNTAX.send(player, "/2 cfi " + argList.get(0) + " <image or mask> <value> [white-only]");
C.COMMAND_SYNTAX.send(player, "/2 cfi " + argList.get(0) + " <value>");
return;
} else if (!StringMan.isEqualIgnoreCaseToAny(argList.get(0), "done", "cancel", "addcaves", "addore", "addores", "addschems", "setheight")) {
C.COMMAND_SYNTAX.send(player, "/2 cfi <setbiome|setoverlay|setmain|setfloor|setcolumn|done|cancel|addcaves|addore[s]|addschems|setheight|setcolor>");
C.COMMAND_SYNTAX.send(player, "/2 cfi <setbiome|setoverlay|setmain|setfloor|setcolumn|done|cancel|addcaves|addore[s]|addschems|setheight|setcolor|setglasscolor>");
return;
}
}
@ -207,6 +207,16 @@ public class CreateFromImage extends Command {
player.sendMessage("Set color, what's next?");
return;
}
case "setglasscolor": {
if (argList.size() != 2) {
C.COMMAND_SYNTAX.send(player, "/2 cfi " + argList.get(0) + " <url>");
return;
}
BufferedImage image = getImgurImage(argList.get(1), fp);
generator.setColorWithGlass(image);
player.sendMessage("Set glass color, what's next?");
return;
}
case "setheight": {
if (argList.size() != 2) {
C.COMMAND_SYNTAX.send(player, "/2 cfi " + argList.get(0) + " <height>");

View File

@ -2,6 +2,7 @@ package com.boydti.fawe.util;
import com.boydti.fawe.FaweCache;
import com.sk89q.worldedit.blocks.BaseBlock;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import java.awt.image.BufferedImage;
import java.io.File;
@ -11,12 +12,64 @@ import org.json.simple.parser.ParseException;
public class CachedTextureUtil extends TextureUtil {
private final TextureUtil parent;
private Int2ObjectOpenHashMap<Integer> colorBlockMap;
private Int2ObjectOpenHashMap<char[]> colorLayerMap;
private int[] validLayerColors;
private char[][] validLayerBlocks;
public CachedTextureUtil(TextureUtil parent) {
super(parent.getFolder());
this.parent = parent;
this.colorBlockMap = new Int2ObjectOpenHashMap<>();
this.colorLayerMap = new Int2ObjectOpenHashMap<>();
Int2ObjectOpenHashMap<char[]> colorLayerMap = new Int2ObjectOpenHashMap<>();
for (int i = 0; i < parent.validBlockIds.length; i++) {
int color = parent.validColors[i];
int combined = parent.validBlockIds[i];
if (hasAlpha(color)) {
for (int j = 0; j < parent.validBlockIds.length; j++) {
int colorOther = parent.validColors[j];
if (!hasAlpha(colorOther)) {
int combinedOther = parent.validBlockIds[j];
int combinedColor = combine(color, colorOther);
colorLayerMap.put(combinedColor, new char[] {(char) combined, (char) combinedOther});
}
}
}
}
this.validLayerColors = new int[colorLayerMap.size()];
this.validLayerBlocks = new char[colorLayerMap.size()][];
int index = 0;
for (Int2ObjectMap.Entry<char[]> entry : colorLayerMap.int2ObjectEntrySet()) {
validLayerColors[index] = entry.getIntKey();
validLayerBlocks[index++] = entry.getValue();
}
}
public char[] getNearestLayer(int color) {
char[] closest = colorLayerMap.get(color);
if (closest != null) {
return closest;
}
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 < validLayerColors.length; i++) {
int other = validLayerColors[i];
if (((other >> 24) & 0xFF) == alpha) {
long distance = colorDistance(red1, green1, blue1, other);
if (distance < min) {
min = distance;
closest = validLayerBlocks[i];
}
}
}
if (closest != null) {
colorLayerMap.put(color, closest);
}
return closest;
}
@Override

View File

@ -34,9 +34,9 @@ import org.json.simple.parser.ParseException;
public class TextureUtil {
private final File folder;
private int[] blockColors = new int[Character.MAX_VALUE + 1];
private int[] validColors;
private int[] validBlockIds;
protected int[] blockColors = new int[Character.MAX_VALUE + 1];
protected int[] validColors;
protected char[] validBlockIds;
public TextureUtil() {
this(MainUtil.getFile(Fawe.imp().getDirectory(), Settings.IMP.PATHS.TEXTURES));
@ -83,6 +83,21 @@ public class TextureUtil {
return folder;
}
protected int combine(int top, int bottom) {
int alpha1 = (top >> 24) & 0xFF;
int alpha2 = 255 - alpha1;
int red1 = (top >> 16) & 0xFF;
int green1 = (top >> 8) & 0xFF;
int blue1 = (top >> 0) & 0xFF;
int red2 = (bottom >> 16) & 0xFF;
int green2 = (bottom >> 8) & 0xFF;
int blue2 = (bottom >> 0) & 0xFF;
int red = ((red1 * alpha1) + (red2 * alpha2)) / 255;
int green = ((green1 * alpha1) + (green2 * alpha2)) / 255;
int blue = ((blue1 * alpha1) + (blue2 * alpha2)) / 255;
return (red << 16) + (green << 8) + (blue << 0) + (255 << 24);
}
public void loadModTextures() throws IOException, ParseException {
Int2ObjectOpenHashMap<Integer> colorMap = new Int2ObjectOpenHashMap<>();
if (folder.exists()) {
@ -162,13 +177,25 @@ public class TextureUtil {
}
// Try to match the textures to a block
Int2ObjectOpenHashMap<String> idMap = new Int2ObjectOpenHashMap<>();
HashSet<Integer> map2 = new HashSet<>();
for (String id : bundled.stateMap.keySet()) {
if (id.startsWith(modId)) {
BaseBlock block = bundled.findByState(id);
BundledBlockData.BlockEntry state = bundled.findById(block.getId());
// Ignore non blocks
if (!state.material.isRenderedAsNormalBlock()) {
continue;
if (!state.material.isFullCube() && !state.material.isRenderedAsNormalBlock()) {
switch (block.getId()) {
case 20:
case 95:
break;
default:
continue;
}
} else if (!state.material.isFullCube() || !state.material.isRenderedAsNormalBlock()) {
switch (block.getId()) {
case 52:
continue;
}
}
if (state.material.getLightValue() != 0) {
continue;
@ -205,14 +232,14 @@ public class TextureUtil {
}
}
// Convert the color map to a simple array
validBlockIds = new int[colorMap.size()];
validBlockIds = new char[colorMap.size()];
validColors = new int[colorMap.size()];
int index = 0;
for (Int2ObjectMap.Entry<Integer> entry : colorMap.int2ObjectEntrySet()) {
int combinedId = entry.getIntKey();
int color = entry.getValue();
blockColors[combinedId] = color;
validBlockIds[index] = combinedId;
validBlockIds[index] = (char) combinedId;
validColors[index] = color;
index++;
}
@ -326,19 +353,19 @@ public class TextureUtil {
}
}
private boolean hasAlpha(int color) {
protected boolean hasAlpha(int color) {
int alpha = (color >> 24) & 0xFF;
return alpha != 255;
}
public long colorDistance(int c1, int c2) {
protected long colorDistance(int c1, int c2) {
int red1 = (c1 >> 16) & 0xFF;
int green1 = (c1 >> 8) & 0xFF;
int blue1 = (c1 >> 0) & 0xFF;
return colorDistance(red1, green1, blue1, c2);
}
private long colorDistance(int red1, int green1, int blue1, int c2) {
protected long colorDistance(int red1, int green1, int blue1, int c2) {
int red2 = (c2 >> 16) & 0xFF;
int green2 = (c2 >> 8) & 0xFF;
int blue2 = (c2 >> 0) & 0xFF;
@ -349,7 +376,7 @@ public class TextureUtil {
return (((512 + rmean) * r * r) >> 8) + 4 * g * g + (((767 - rmean) * b * b) >> 8);
}
public int getColor(BufferedImage image) {
protected int getColor(BufferedImage image) {
int width = image.getWidth();
int height = image.getHeight();
long totalRed = 0;