ImageSampler implementation

This commit is contained in:
dfsek
2021-01-29 10:09:19 -07:00
parent 02d61d0764
commit e306a0fd09
8 changed files with 148 additions and 58 deletions

View File

@@ -0,0 +1,36 @@
package com.dfsek.terra.api.math.noise.samplers;
public class DomainWarpedSampler implements NoiseSampler {
private final NoiseSampler function;
private final NoiseSampler warp;
private final int seed;
public DomainWarpedSampler(NoiseSampler function, NoiseSampler warp, int seed) {
this.function = function;
this.warp = warp;
this.seed = seed;
}
@Override
public double getNoise(double x, double y) {
return function.getNoise(
x + warp.getNoiseSeeded(seed, x, y),
y + warp.getNoiseSeeded(seed + 1, x, y)
);
}
@Override
public double getNoise(double x, double y, double z) {
return 0;
}
@Override
public double getNoiseSeeded(int seed, double x, double y) {
return 0;
}
@Override
public double getNoiseSeeded(int seed, double x, double y, double z) {
return 0;
}
}

View File

@@ -295,7 +295,7 @@ public class FastNoiseLite implements NoiseSampler {
private CellularDistanceFunction mCellularDistanceFunction = CellularDistanceFunction.EuclideanSq;
private CellularReturnType mCellularReturnType = CellularReturnType.Distance;
private double mCellularJitterModifier = 1.0;
private DomainWarpType mDomainWarpType = DomainWarpType.None;
private DomainWarpType mDomainWarpType = DomainWarpType.OpenSimplex2;
private TransformType3D mWarpTransformType3D = TransformType3D.DefaultOpenSimplex2;
private double mDomainWarpAmp = 1.0;
private NoiseSampler cellularNoiseLookup = CELLULAR_LOOKUP_DEFAULT;
@@ -652,12 +652,6 @@ public class FastNoiseLite implements NoiseSampler {
@Override
public double getNoiseSeeded(int seed, double x, double y) {
if(!mDomainWarpType.equals(DomainWarpType.None)) {
Vector2 dWarp = new Vector2(x, y);
domainWarp(dWarp);
x = dWarp.getX();
y = dWarp.getZ();
}
x *= mFrequency;
y *= mFrequency;
@@ -691,14 +685,6 @@ public class FastNoiseLite implements NoiseSampler {
@Override
public double getNoiseSeeded(int seed, double x, double y, double z) {
if(!mDomainWarpType.equals(DomainWarpType.None)) {
Vector3 dWarp = new Vector3(x, y, z);
domainWarp(dWarp);
x = dWarp.getX();
y = dWarp.getY();
z = dWarp.getZ();
}
x *= mFrequency;
y *= mFrequency;
z *= mFrequency;
@@ -2658,8 +2644,7 @@ public class FastNoiseLite implements NoiseSampler {
OpenSimplex2,
OpenSimplex2Reduced,
BasicGrid,
Function,
None
Function
}

View File

@@ -0,0 +1,69 @@
package com.dfsek.terra.api.math.noise.samplers;
import net.jafama.FastMath;
import java.awt.image.BufferedImage;
public class ImageSampler implements NoiseSampler {
private final BufferedImage image;
private final Channel channel;
private final double frequency;
public ImageSampler(BufferedImage image, Channel channel, double frequency) {
this.image = image;
this.channel = channel;
this.frequency = frequency;
}
@Override
public double getNoise(double x, double y) {
return ((channel.getChannel(image.getRGB(FastMath.floorMod(FastMath.floorToInt(x * frequency), image.getWidth()), FastMath.floorMod(FastMath.floorToInt(y * frequency), image.getHeight()))) / 255D) - 0.5) * 2;
}
@Override
public double getNoise(double x, double y, double z) {
return getNoise(x, y);
}
@Override
public double getNoiseSeeded(int seed, double x, double y) {
return getNoise(x, y);
}
@Override
public double getNoiseSeeded(int seed, double x, double y, double z) {
return getNoise(x, y, z);
}
public enum Channel {
RED {
@Override
public int getChannel(int mashed) {
return (mashed >> 16) & 0xff;
}
}, GREEN {
@Override
public int getChannel(int mashed) {
return (mashed >> 8) & 0xff;
}
}, BLUE {
@Override
public int getChannel(int mashed) {
return mashed & 0xff;
}
}, GRAYSCALE {
@Override
public int getChannel(int mashed) {
return (RED.getChannel(mashed) + GREEN.getChannel(mashed) + BLUE.getChannel(mashed)) / 3;
}
}, ALPHA {
@Override
public int getChannel(int mashed) {
return (mashed >> 24) & 0xff;
}
};
public abstract int getChannel(int mashed);
}
}

View File

@@ -8,7 +8,6 @@ import com.dfsek.terra.api.math.ProbabilityCollection;
import com.dfsek.terra.api.math.Range;
import com.dfsek.terra.api.math.noise.normalizer.Normalizer;
import com.dfsek.terra.api.math.noise.samplers.FastNoiseLite;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.api.world.palette.holder.PaletteHolder;
import com.dfsek.terra.api.world.palette.holder.PaletteLayerHolder;
import com.dfsek.terra.config.loaders.MaterialSetLoader;
@@ -19,7 +18,6 @@ import com.dfsek.terra.config.loaders.config.GridSpawnLoader;
import com.dfsek.terra.config.loaders.config.OreConfigLoader;
import com.dfsek.terra.config.loaders.config.OreHolderLoader;
import com.dfsek.terra.config.loaders.config.TreeLayerLoader;
import com.dfsek.terra.config.loaders.config.sampler.NoiseSamplerBuilderLoader;
import com.dfsek.terra.config.loaders.palette.PaletteHolderLoader;
import com.dfsek.terra.config.loaders.palette.PaletteLayerLoader;
import com.dfsek.terra.util.MaterialSet;
@@ -58,7 +56,6 @@ public class GenericLoaders implements LoaderRegistrar {
.registerLoader(FastNoiseLite.CellularDistanceFunction.class, (t, object, cf) -> FastNoiseLite.CellularDistanceFunction.valueOf((String) object))
.registerLoader(Normalizer.NormalType.class, (t, o, l) -> Normalizer.NormalType.valueOf(o.toString().toUpperCase()))
.registerLoader(TerraFlora.Search.class, (t, o, l) -> TerraFlora.Search.valueOf(o.toString()))
.registerLoader(Normalizer.NormalType.class, (t, o, l) -> Normalizer.NormalType.valueOf(o.toString().toUpperCase()))
.registerLoader(NoiseSeeded.class, new NoiseSamplerBuilderLoader());
.registerLoader(Normalizer.NormalType.class, (t, o, l) -> Normalizer.NormalType.valueOf(o.toString().toUpperCase()));
}
}

View File

@@ -8,15 +8,26 @@ import com.dfsek.tectonic.loading.TypeLoader;
import com.dfsek.terra.api.math.noise.normalizer.LinearNormalizer;
import com.dfsek.terra.api.math.noise.normalizer.NormalNormalizer;
import com.dfsek.terra.api.math.noise.normalizer.Normalizer;
import com.dfsek.terra.api.math.noise.samplers.ImageSampler;
import com.dfsek.terra.api.math.noise.samplers.NoiseSampler;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.config.fileloaders.Loader;
import com.dfsek.terra.world.generation.config.NoiseBuilder;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.Map;
@SuppressWarnings("unchecked")
public class NoiseSamplerBuilderLoader implements TypeLoader<NoiseSeeded> {
private final Loader fileAccess;
public NoiseSamplerBuilderLoader(Loader fileAccess) {
this.fileAccess = fileAccess;
}
@Override
public NoiseSeeded load(Type t, Object c, ConfigLoader loader) throws LoadException {
Map<String, Object> map = (Map<String, Object>) c;
@@ -100,6 +111,25 @@ public class NoiseSamplerBuilderLoader implements TypeLoader<NoiseSeeded> {
};
}
}
} else if(samplerType.equals("IMAGE")) {
try {
BufferedImage image = ImageIO.read(fileAccess.get(map.get("image").toString()));
ImageSampler.Channel channel = ImageSampler.Channel.valueOf(map.get("channel").toString());
double frequency = Double.parseDouble(map.get("frequency").toString());
return new NoiseSeeded() {
@Override
public NoiseSampler apply(Long seed) {
return new ImageSampler(image, channel, frequency);
}
@Override
public int getDimensions() {
return dimensions;
}
};
} catch(IOException | NullPointerException e) {
throw new LoadException("Failed to load image", e);
}
}
throw new LoadException("No such noise sampler type \"" + samplerType + "\"");

View File

@@ -9,6 +9,7 @@ import com.dfsek.terra.api.LoaderRegistrar;
import com.dfsek.terra.api.core.TerraPlugin;
import com.dfsek.terra.api.structures.loot.LootTable;
import com.dfsek.terra.api.structures.script.StructureScript;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.api.world.flora.Flora;
import com.dfsek.terra.api.world.palette.Palette;
import com.dfsek.terra.api.world.tree.Tree;
@@ -27,6 +28,7 @@ import com.dfsek.terra.config.fileloaders.Loader;
import com.dfsek.terra.config.fileloaders.ZIPLoader;
import com.dfsek.terra.config.lang.LangUtil;
import com.dfsek.terra.config.loaders.config.biome.BiomeProviderBuilderLoader;
import com.dfsek.terra.config.loaders.config.sampler.NoiseSamplerBuilderLoader;
import com.dfsek.terra.config.templates.AbstractableTemplate;
import com.dfsek.terra.config.templates.BiomeTemplate;
import com.dfsek.terra.config.templates.FloraTemplate;
@@ -238,7 +240,8 @@ public class ConfigPack implements LoaderRegistrar {
.registerLoader(StructureScript.class, scriptRegistry)
.registerLoader(TerraStructure.class, structureRegistry)
.registerLoader(LootTable.class, lootRegistry)
.registerLoader(BiomeProvider.BiomeProviderBuilder.class, new BiomeProviderBuilderLoader(main, biomeRegistry, loader));
.registerLoader(BiomeProvider.BiomeProviderBuilder.class, new BiomeProviderBuilderLoader(main, biomeRegistry, loader))
.registerLoader(NoiseSeeded.class, new NoiseSamplerBuilderLoader(loader));
}
public ScriptRegistry getScriptRegistry() {

View File

@@ -57,18 +57,6 @@ public class NoiseBuilder implements ConfigTemplate {
@Default
private double cellularJitter = 1.0D;
@Value("domain-warp.type")
@Default
private FastNoiseLite.DomainWarpType domainWarpType = FastNoiseLite.DomainWarpType.None;
@Value("domain-warp.amplitude")
@Default
private double domainWarpAmp = 1.0D;
@Value("domain-warp.function")
@Default
private NoiseSeeded domainWarp;
@Value("rotation-type")
@Default
private FastNoiseLite.RotationType3D rotationType3D = FastNoiseLite.RotationType3D.None;
@@ -101,10 +89,6 @@ public class NoiseBuilder implements ConfigTemplate {
noise.setNoiseType(type);
noise.setDomainWarpType(domainWarpType);
noise.setDomainWarpAmp(domainWarpAmp);
if(domainWarp != null) noise.setDomainWarpFunction(domainWarp.apply(seed));
noise.setRotationType3D(rotationType3D);
noise.setFrequency(frequency);
@@ -146,15 +130,6 @@ public class NoiseBuilder implements ConfigTemplate {
return this;
}
public FastNoiseLite.DomainWarpType getDomainWarpType() {
return domainWarpType;
}
public NoiseBuilder setDomainWarpType(FastNoiseLite.DomainWarpType domainWarpType) {
this.domainWarpType = domainWarpType;
return this;
}
public double getCellularJitter() {
return cellularJitter;
}
@@ -164,15 +139,6 @@ public class NoiseBuilder implements ConfigTemplate {
return this;
}
public double getDomainWarpAmp() {
return domainWarpAmp;
}
public NoiseBuilder setDomainWarpAmp(double domainWarpAmp) {
this.domainWarpAmp = domainWarpAmp;
return this;
}
public double getFractalGain() {
return fractalGain;
}

View File

@@ -6,6 +6,7 @@ import com.dfsek.terra.api.math.ProbabilityCollection;
import com.dfsek.terra.api.math.noise.samplers.NoiseSampler;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.config.GenericLoaders;
import com.dfsek.terra.config.fileloaders.FolderLoader;
import com.dfsek.terra.config.loaders.ProbabilityCollectionLoader;
import com.dfsek.terra.config.loaders.config.sampler.NoiseSamplerBuilderLoader;
import org.apache.commons.io.FileUtils;
@@ -18,6 +19,7 @@ import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.AtomicInteger;
@@ -90,10 +92,12 @@ public class NoiseTool {
private static BufferedImage load(int seed, boolean distribution, boolean chunk) throws ConfigException, IOException {
long s = System.nanoTime();
FolderLoader folderLoader = new FolderLoader(Paths.get("./"));
ConfigLoader loader = new ConfigLoader();
loader.registerLoader(NoiseSeeded.class, new NoiseSamplerBuilderLoader())
loader.registerLoader(NoiseSeeded.class, new NoiseSamplerBuilderLoader(folderLoader))
.registerLoader(ProbabilityCollection.class, new ProbabilityCollectionLoader());
new GenericLoaders(null).register(loader);
NoiseConfigTemplate template = new NoiseConfigTemplate();