diff --git a/src/main/java/com/volmit/iris/util/uniques/U.java b/src/main/java/com/volmit/iris/util/uniques/U.java new file mode 100644 index 000000000..b069dab6a --- /dev/null +++ b/src/main/java/com/volmit/iris/util/uniques/U.java @@ -0,0 +1,20 @@ +package com.volmit.iris.util.uniques; + +import java.io.File; + +public class U { + public static void main(String[] a) + { + UniqueRenderer r = new UniqueRenderer("helloworld", 2560 , 1440); + + r.writeCollectionFrames(new File("collection"), 1, 1024); + + for(int i = 1; i <= 1024; i++) + { + r.writeAnimation(new File("collection/animation"), 2, 0, 32, 1); + } + + + System.exit(0); + } +} diff --git a/src/main/java/com/volmit/iris/util/uniques/UBufferedImage.java b/src/main/java/com/volmit/iris/util/uniques/UBufferedImage.java new file mode 100644 index 000000000..3211d49a2 --- /dev/null +++ b/src/main/java/com/volmit/iris/util/uniques/UBufferedImage.java @@ -0,0 +1,51 @@ +package com.volmit.iris.util.uniques; + +import java.awt.*; +import java.awt.image.BufferedImage; +import java.awt.image.ColorModel; +import java.awt.image.WritableRaster; + +public class UBufferedImage implements UImage { + private final BufferedImage buf; + + public UBufferedImage(BufferedImage buf) + { + this.buf = buf; + } + + @Override + public int getWidth() { + return buf.getWidth(); + } + + @Override + public int getHeight() { + return buf.getHeight(); + } + + @Override + public UImage copy() { + ColorModel cm = buf.getColorModel(); + boolean isAlphaPremultiplied = cm.isAlphaPremultiplied(); + WritableRaster raster = buf.copyData(null); + return new UBufferedImage(new BufferedImage(cm, raster, isAlphaPremultiplied, null)); + } + + @Override + public Color get(int x, int y) { + return new Color(buf.getRGB(x, y)); + } + + @Override + public void set(int x, int y, Color color) { + try + { + buf.setRGB(x, y, color.getRGB()); + } + + catch(Throwable e) + { + + } + } +} diff --git a/src/main/java/com/volmit/iris/util/uniques/UFeature.java b/src/main/java/com/volmit/iris/util/uniques/UFeature.java new file mode 100644 index 000000000..a06ccd00b --- /dev/null +++ b/src/main/java/com/volmit/iris/util/uniques/UFeature.java @@ -0,0 +1,77 @@ +package com.volmit.iris.util.uniques; + +import com.volmit.iris.engine.object.NoiseStyle; +import com.volmit.iris.util.function.Function2; +import com.volmit.iris.util.function.NoiseInjector; +import com.volmit.iris.util.interpolation.InterpolationMethod; +import com.volmit.iris.util.math.RNG; +import com.volmit.iris.util.noise.CNG; +import com.volmit.iris.util.stream.ProceduralStream; +import com.volmit.iris.util.stream.interpolation.Interpolated; + +import java.awt.*; +import java.awt.image.BufferedImage; +import java.util.List; +import java.util.function.Consumer; + +public interface UFeature { + List injectors = List.of( + CNG.ADD, + CNG.DST_MOD, + CNG.DST_POW, + CNG.DST_SUBTRACT, + CNG.MAX, + CNG.MIN, + CNG.SRC_MOD, + CNG.SRC_POW, + CNG.SRC_SUBTRACT, + CNG.MULTIPLY + ); + + void render(UImage image, RNG rng, double time, Consumer progressor, UFeatureMeta meta); + + default Color color(CNG hue, CNG saturation, CNG brightness, double x, double y, double t) + { + return Color.getHSBColor((float)hue.fitDouble(0, 1, x + t, y + t), + (float)saturation.fitDouble(0, 1, x + t, y + t), + (float)brightness.fitDouble(0, 1, x + t, y + t)); + } + + default InterpolationMethod interpolator(RNG rng) + { + return rng.pick( + UniqueRenderer.renderer.getInterpolators() + ); + } + + default CNG generator(String key, RNG rng, double scaleMod, long salt, UFeatureMeta meta) + { + return generator(key, rng, scaleMod, rng.i(1, 3), rng.i(1, 5), salt, meta); + } + + default CNG generator(String key, RNG rng, double scaleMod, int fractures, int composites, long salt, UFeatureMeta meta) + { + RNG rngg = rng.nextParallelRNG(salt); + CNG cng = rng.pick(UniqueRenderer.renderer.getStyles()).create(rngg).oct(rng.i(1, 5)); + RNG rngf = rngg.nextParallelRNG(-salt); + cng.scale(rngf.d(0.33 * scaleMod, 1.66 * scaleMod)); + + if(fractures > 0) + { + cng.fractureWith(generator(null, rngf.nextParallelRNG(salt + fractures), scaleMod / rng.d(4, 17), fractures-1, composites, salt + fractures + 55, null), scaleMod * rngf.nextDouble(16, 256)); + } + + for(int i = 0; i < composites; i++) + { + CNG sub = generator(null, rngf.nextParallelRNG(salt + fractures), scaleMod * rngf.d(0.4, 3.3), fractures / 3, 0, salt + fractures + composites + 78, null); + sub.setInjector(rng.pick(injectors)); + cng.child(sub); + } + + if(key != null && meta != null) + { + meta.registerGenerator(key, cng); + } + return cng; + } +} diff --git a/src/main/java/com/volmit/iris/util/uniques/UFeatureMeta.java b/src/main/java/com/volmit/iris/util/uniques/UFeatureMeta.java new file mode 100644 index 000000000..068e65023 --- /dev/null +++ b/src/main/java/com/volmit/iris/util/uniques/UFeatureMeta.java @@ -0,0 +1,103 @@ +package com.volmit.iris.util.uniques; + +import com.volmit.iris.engine.object.NoiseStyle; +import com.volmit.iris.util.collection.KList; +import com.volmit.iris.util.collection.KMap; +import com.volmit.iris.util.function.NoiseInjector; +import com.volmit.iris.util.interpolation.InterpolationMethod; +import com.volmit.iris.util.interpolation.IrisInterpolation; +import com.volmit.iris.util.noise.CNG; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Data +@NoArgsConstructor +public class UFeatureMeta { + private KMap interpolators; + private KMap generators; + private String feature; + + public void registerInterpolator(String key, InterpolationMethod method, double radius) + { + if(interpolators == null) + { + interpolators = new KMap<>(); + } + interpolators.put(key, new UFeatureMetaInterpolator(method, radius)); + } + + public void registerGenerator(String key, CNG cng) + { + if(generators == null) + { + generators = new KMap<>(); + } + generators.put(key, buildGenerator(cng)); + } + + public UFeatureMetaGenerator buildGenerator(CNG cng) + { + UFeatureMetaGenerator g = new UFeatureMetaGenerator(); + g.setStyle(cng.getLeakStyle()); + g.setScale(cng.getScale()); + g.setOctaves(cng.getOct()); + + if(cng.getFracture() != null) + { + g.setFracture(buildGenerator(cng.getFracture())); + g.setFractureMultiplier(cng.getFscale()); + } + + if(cng.getChildren() != null && cng.getChildren().isNotEmpty()) + { + g.setChildren(new KList<>()); + + for(CNG i : cng.getChildren()) + { + g.getChildren().add(buildGenerator(i)); + } + } + + if(cng.getInjector() == CNG.ADD){g.setParentInject("add");} + else if(cng.getInjector() == CNG.SRC_SUBTRACT){g.setParentInject("src_subtract");} + else if(cng.getInjector() == CNG.DST_SUBTRACT){g.setParentInject("dst_subtract");} + else if(cng.getInjector() == CNG.MULTIPLY ){g.setParentInject("multiply");} + else if(cng.getInjector() == CNG.MAX){g.setParentInject("max");} + else if(cng.getInjector() == CNG.MIN){g.setParentInject("min");} + else if(cng.getInjector() == CNG.SRC_MOD ){g.setParentInject("src_mod");} + else if(cng.getInjector() == CNG.SRC_POW ){g.setParentInject("src_pow");} + else if(cng.getInjector() == CNG.DST_MOD ){g.setParentInject("dst_mod");} + else if(cng.getInjector() == CNG.DST_POW){g.setParentInject("dst_pow");} + + return g; + } + + public boolean isEmpty() { + return (interpolators == null || interpolators.isEmpty()) && (generators == null || generators.isEmpty()); + } + + @Data + @NoArgsConstructor + @AllArgsConstructor + static class UFeatureMetaInterpolator + { + private InterpolationMethod interpolator; + private double radius; + } + + @Data + @NoArgsConstructor + static class UFeatureMetaGenerator + { + private NoiseStyle style; + private int octaves = 1; + private double scale = 1; + private String parentInject; + private UFeatureMetaGenerator fracture; + private Double fractureMultiplier; + private List children; + } +} diff --git a/src/main/java/com/volmit/iris/util/uniques/UImage.java b/src/main/java/com/volmit/iris/util/uniques/UImage.java new file mode 100644 index 000000000..821584a64 --- /dev/null +++ b/src/main/java/com/volmit/iris/util/uniques/UImage.java @@ -0,0 +1,20 @@ +package com.volmit.iris.util.uniques; + +import java.awt.*; + +public interface UImage { + int getWidth(); + + int getHeight(); + + default boolean isInBounds(int x, int y) + { + return x >= 0 && x < getWidth() && y >= 0 && y < getHeight(); + } + + UImage copy(); + + Color get(int x, int y); + + void set(int x, int y, Color color); +} diff --git a/src/main/java/com/volmit/iris/util/uniques/UMeta.java b/src/main/java/com/volmit/iris/util/uniques/UMeta.java new file mode 100644 index 000000000..f5ba9aae6 --- /dev/null +++ b/src/main/java/com/volmit/iris/util/uniques/UMeta.java @@ -0,0 +1,56 @@ +package com.volmit.iris.util.uniques; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.volmit.iris.engine.object.NoiseStyle; +import com.volmit.iris.util.collection.KList; +import com.volmit.iris.util.collection.KMap; +import com.volmit.iris.util.interpolation.InterpolationMethod; +import com.volmit.iris.util.io.IO; +import com.volmit.iris.util.noise.CNG; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.util.List; + +@Data +@NoArgsConstructor +public class UMeta { + private transient BufferedImage image; + private KMap features; + private long id; + private double time; + private int width; + private int height; + + public void registerFeature(String key, UFeatureMeta feature) + { + if(features == null) + { + features = new KMap<>(); + } + + features.put(key, feature); + } + + public void export(File destination) throws IOException { + + for(String i : features.k()) + { + if(features.get(i).isEmpty()) + { + features.remove(i); + } + } + + width = image.getWidth(); + height = image.getHeight(); + ImageIO.write(image, "PNG", destination); + IO.writeAll(new File(destination.getParentFile(), destination.getName() + ".json"), new GsonBuilder().setPrettyPrinting().create().toJson(this)); + } +} diff --git a/src/main/java/com/volmit/iris/util/uniques/UniqueRenderer.java b/src/main/java/com/volmit/iris/util/uniques/UniqueRenderer.java new file mode 100644 index 000000000..55b44b467 --- /dev/null +++ b/src/main/java/com/volmit/iris/util/uniques/UniqueRenderer.java @@ -0,0 +1,338 @@ +package com.volmit.iris.util.uniques; + +import com.volmit.iris.Iris; +import com.volmit.iris.engine.object.NoiseStyle; +import com.volmit.iris.util.collection.KList; +import com.volmit.iris.util.collection.KMap; +import com.volmit.iris.util.format.Form; +import com.volmit.iris.util.function.NoiseProvider; +import com.volmit.iris.util.interpolation.InterpolationMethod; +import com.volmit.iris.util.interpolation.IrisInterpolation; +import com.volmit.iris.util.math.RNG; +import com.volmit.iris.util.noise.CNG; +import com.volmit.iris.util.parallel.BurstExecutor; +import com.volmit.iris.util.parallel.MultiBurst; +import com.volmit.iris.util.scheduling.ChronoLatch; +import com.volmit.iris.util.scheduling.J; +import com.volmit.iris.util.scheduling.PrecisionStopwatch; +import com.volmit.iris.util.stream.ProceduralStream; +import com.volmit.iris.util.uniques.features.*; + +import javax.imageio.ImageIO; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.File; +import java.util.List; +import java.util.Locale; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicInteger; + +public class UniqueRenderer { + static UniqueRenderer renderer; + + static final List backgrounds = List.of(new UFWarpedBackground()); + static final List interpolators = List.of(new UFInterpolator(), new UFNOOP()); + static final List features = List.of(new UFWarpedLines(), new UFWarpedDisc(), new UFWarpedDots(), new UFWarpedCircle()); + private final String seed; + private final ProceduralStream spatialSeed; + private final int width; + private final int height; + private final KMap writing = new KMap<>(); + private KList sortedStyles = new KList(); + private KList sortedInterpolators = new KList(); + int cores = Runtime.getRuntime().availableProcessors(); + private final ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); + + public UniqueRenderer(String seed, int width, int height) + { + renderer = this; + computeNoiseStyles(3000, 2); + computeInterpolationMethods(3000, 2); + this.seed = seed; + this.width = width; + this.height = height; + spatialSeed = NoiseStyle.FRACTAL_WATER.stream(new RNG(seed)).convert((d) -> new RNG(Math.round(seed.hashCode() + (d * 934321234D)))); + new Thread(() -> { + while(true) + { + J.sleep(5000); + + if(!writing.isEmpty()) + { + System.out.println(Form.repeat("\n", 60)); + System.out.println(Form.memSize(Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(), 2) + " of " + Form.memSize(Runtime.getRuntime().totalMemory(), 2)); + KMap c = writing.copy(); + + for(String i : writing.k().sort()) + { + String prog = ""; + String f = writing.get(i); + + if(f.contains("%")) + { + String v = f.split("\\Q%\\E")[0]; + try + { + prog = drawProgress(Double.valueOf(Integer.parseInt(v.substring(v.length() - 2))) / 100D, 30); + } + + catch(Throwable e) + { + try + { + prog = drawProgress(Double.valueOf(Integer.parseInt(v.substring(v.length() - 1))) / 100D, 30); + } + + catch(Throwable ee) + { + try + { + prog = drawProgress(Double.valueOf(Integer.parseInt(v.substring(v.length() - 3))) / 100D, 30); + } + + catch(Throwable eee) + { + + } + } + } + } + + System.out.println(prog + " " + i + " => " + f); + } + } + } + }).start(); + } + + public UMeta renderFrameBuffer(long id, double t) + { + UMeta meta = new UMeta(); + meta.setId(id); + meta.setTime(t); + RNG rng = spatialSeed.get(id, id + ((id * id) % (id / 3D))); + RNG rngbg = spatialSeed.get(id, -id + ((id * id) % (id / 4D))); + BufferedImage buf = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + BufferedImage bufFG = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + UImage image = new UBufferedImage(buf); + UImage imageFG = new UBufferedImage(bufFG); + ChronoLatch cl = new ChronoLatch(250); + UFeature background = rng.pick(backgrounds); + UFeature interpolator = rng.pick(interpolators); + UFeature foreground = rng.pick(features); + UFeature foregroundInterpolator = rng.pick(interpolators); + UFeatureMeta backgroundMeta = new UFeatureMeta(); + UFeatureMeta foregroundMeta = new UFeatureMeta(); + UFeatureMeta backgroundInterpolatorMeta = new UFeatureMeta(); + UFeatureMeta foregroundInterpolatorMeta = new UFeatureMeta(); + background.render(image, rngbg, t, (p) -> { + if(cl.flip()) + { + writing.put("#" + id + ":" + t, Form.pc(p / 4D) + " [" + background.getClass().getSimpleName() + " " + Form.pc(p) + "]"); + } + }, backgroundMeta); + backgroundMeta.setFeature(background.getClass().getSimpleName()); + meta.registerFeature("background", backgroundMeta); + interpolator.render(image, rng, t, (p) -> { + if(cl.flip()) + { + writing.put("#" + id + ":" + t, Form.pc(0.25 + (p / 4d)) + " [" + interpolator.getClass().getSimpleName() + " " + Form.pc(p) + "]"); + } + }, backgroundInterpolatorMeta); + backgroundInterpolatorMeta.setFeature(interpolator.getClass().getSimpleName()); + meta.registerFeature("backgroundInterpolator", backgroundInterpolatorMeta); + foreground.render(imageFG, rng, t, (p) -> { + if(cl.flip()) + { + writing.put("#" + id + ":" + t, Form.pc(0.5 + (p / 4d)) + " [" + foreground.getClass().getSimpleName() + " " + Form.pc(p) + "]"); + } + }, foregroundMeta); + foregroundMeta.setFeature(foreground.getClass().getSimpleName()); + meta.registerFeature("foreground", foregroundMeta); + overlay(imageFG, bufFG, image); + foregroundInterpolator.render(image, rng, t, (p) -> { + if(cl.flip()) + { + writing.put("#" + id + ":" + t, Form.pc(0.75 + (p / 4d)) + " [" + interpolator.getClass().getSimpleName() + " " + Form.pc(p) + "]"); + } + }, foregroundInterpolatorMeta); + foregroundInterpolatorMeta.setFeature(foregroundInterpolator.getClass().getSimpleName()); + meta.registerFeature("foregroundInterpolator", foregroundInterpolatorMeta); + overlay(imageFG, bufFG, image); + meta.setImage(buf); + writing.remove("#" + id + ":" + t); + return meta; + } + +private void overlay(UImage layer, BufferedImage layerBuf, UImage onto) +{ + for(int i = 0; i < onto.getWidth(); i++) + { + for(int j = 0; j < onto.getHeight(); j++) + { + if(layerBuf.getRGB(i, j) != 0) + { + onto.set(i, j, layer.get(i, j)); + } + } + } +} + + private String drawProgress(double progress, int len) + { + int max = len; + int in = (int) Math.round(progress * max); + max -= in; + + return "[" + Form.repeat("=", in) + Form.repeat(" ", max)+ "]"; + } + + private void computeNoiseStyles(double time, double scope) { + List allowedStyles = new KList<>(NoiseStyle.values()); + allowedStyles.remove(NoiseStyle.FLAT); + KMap speeds = new KMap<>(); + double allocateMS = time; + double maxTestDuration = allocateMS / allowedStyles.size(); + System.out.println("Running Noise Style Benchmark for " + Form.duration(allocateMS, 0) + "."); + System.out.println("Benchmarking " + allowedStyles.size() + " + Noise Styles for " + Form.duration(maxTestDuration, 1) + " each."); + System.out.println(); + + for(NoiseStyle i : allowedStyles) + { + int score = 0; + CNG cng = i.create(new RNG("renderspeedtest")); + PrecisionStopwatch p = PrecisionStopwatch.start(); + double g = 0; + while(p.getMilliseconds() < maxTestDuration) + { + cng.noise(g, -g * 2); + g+= 0.1; + g *= 1.25; + score++; + } + + speeds.put(i, score); + } + + for(NoiseStyle i : speeds.sortKNumber()) + { + System.out.println(Form.capitalizeWords(i.name().toLowerCase(Locale.ROOT).replaceAll("\\Q_\\E", " ")) + " => " + Form.f(speeds.get(i))); + } + System.out.println(); + int takeUpTo = (int) Math.max(1, scope * speeds.size()); + System.out.println("Choosing the fastest " + Form.pc(scope) + " styles (" + takeUpTo + ")"); + + for(NoiseStyle i : speeds.sortKNumber().reverse()) + { + if(takeUpTo-- <= 0) + { + break; + } + + sortedStyles.add(i); + System.out.println("- " + Form.capitalizeWords(i.name().toLowerCase(Locale.ROOT).replaceAll("\\Q_\\E", " "))); + } + } + + private void computeInterpolationMethods(double time, double scope) { + List allowedStyles = new KList<>(InterpolationMethod.values()); + allowedStyles.remove(InterpolationMethod.NONE); + KMap speeds = new KMap<>(); + double allocateMS = time; + double maxTestDuration = allocateMS / allowedStyles.size(); + System.out.println("Running Interpolation Method Benchmark for " + Form.duration(allocateMS, 0) + "."); + System.out.println("Benchmarking " + allowedStyles.size() + " + Interpolation Methods for " + Form.duration(maxTestDuration, 1) + " each."); + System.out.println(); + + RNG r = new RNG("renderspeedtestinterpolation"); + CNG cng = NoiseStyle.SIMPLEX.create(r); + NoiseProvider np = (x, z) -> cng.noise(x, z); + + for(InterpolationMethod i : allowedStyles) + { + int score = 0; + + PrecisionStopwatch p = PrecisionStopwatch.start(); + double g = 0; + while(p.getMilliseconds() < maxTestDuration) + { + IrisInterpolation.getNoise(i, (int) g, (int) (-g * 2.225), r.d(4, 64), np); + cng.noise(g, -g * 2); + g+= 1.1; + g *= 1.25; + score++; + } + + speeds.put(i, score); + } + + for(InterpolationMethod i : speeds.sortKNumber()) + { + System.out.println(Form.capitalizeWords(i.name().toLowerCase(Locale.ROOT).replaceAll("\\Q_\\E", " ")) + " => " + Form.f(speeds.get(i))); + } + System.out.println(); + int takeUpTo = (int) Math.max(1, scope * speeds.size()); + System.out.println("Choosing the fastest " + Form.pc(scope) + " interpolators (" + takeUpTo + ")"); + + for(InterpolationMethod i : speeds.sortKNumber().reverse()) + { + if(takeUpTo-- <= 0) + { + break; + } + + sortedInterpolators.add(i); + System.out.println("- " + Form.capitalizeWords(i.name().toLowerCase(Locale.ROOT).replaceAll("\\Q_\\E", " "))); + } + } + + public void writeCollectionFrames(File folder, int fromId, int toId) + { + folder.mkdirs(); + BurstExecutor burst = new BurstExecutor(executor, 10); + burst.setMulticore(false); + AtomicInteger ai = new AtomicInteger(0); + int max = toId - fromId; + + for(int i = fromId; i <= toId; i++) + { + int ii = i; + burst.queue(() -> { + + writing.put("!#[" + fromId + "-" + toId + "] Collection", ai.get() + " of " + max + " (" + Form.pc(ai.get() / (double)max, 0) + ")"); + writeFrame(new File(folder, ii + ".png"), ii, 0); + ai.incrementAndGet(); + writing.put("!#[" + fromId + "-" + toId + "] Collection", ai.get() + " of " + max + " (" + Form.pc(ai.get() /(double) max, 0) + ")"); + }); + } + + burst.complete(); + writing.remove("!#[" + fromId + "-" + toId + "] Collection"); + } + + public void writeFrame(File destination, long id, double t) { + try + { + renderFrameBuffer(id, t).export(destination); + } + + catch(Throwable e) + { + e.printStackTrace(); + } + } + + public void report(String s) + { + System.out.println(s); + } + + public KList getStyles() { + return sortedStyles; + } + + public List getInterpolators() { + return sortedInterpolators; + } +} diff --git a/src/main/java/com/volmit/iris/util/uniques/features/UFInterpolator.java b/src/main/java/com/volmit/iris/util/uniques/features/UFInterpolator.java new file mode 100644 index 000000000..e2cfecf8f --- /dev/null +++ b/src/main/java/com/volmit/iris/util/uniques/features/UFInterpolator.java @@ -0,0 +1,64 @@ +package com.volmit.iris.util.uniques.features; + +import com.volmit.iris.util.function.NoiseProvider; +import com.volmit.iris.util.interpolation.InterpolationMethod; +import com.volmit.iris.util.interpolation.IrisInterpolation; +import com.volmit.iris.util.math.M; +import com.volmit.iris.util.math.RNG; +import com.volmit.iris.util.noise.CNG; +import com.volmit.iris.util.uniques.UFeature; +import com.volmit.iris.util.uniques.UFeatureMeta; +import com.volmit.iris.util.uniques.UImage; +import com.volmit.iris.util.uniques.UniqueRenderer; + +import java.awt.*; +import java.util.function.Consumer; + +public class UFInterpolator implements UFeature { + @Override + public void render(UImage image, RNG rng, double t, Consumer progressor, UFeatureMeta meta) { + UImage ref = image.copy(); + CNG rmod = generator("interpolator_radius", rng, 1, 33004, meta); + + NoiseProvider nHue = (x, y) -> { + int ix = Math.abs(((int)x)%ref.getWidth()); + int iy = Math.abs(((int)y)%ref.getHeight()); + Color color = ref.get(ix, iy); + float[] hsv = new float[3]; + Color.RGBtoHSB(color.getRed(), color.getGreen(), color.getGreen(), hsv); + return hsv[0]; + }; + NoiseProvider nSat = (x, y) -> { + int ix = Math.abs(((int)x)%ref.getWidth()); + int iy = Math.abs(((int)y)%ref.getHeight()); + Color color = ref.get(ix, iy); + float[] hsv = new float[3]; + Color.RGBtoHSB(color.getRed(), color.getGreen(), color.getGreen(), hsv); + return hsv[1]; + }; + NoiseProvider nBri = (x, y) -> { + int ix = Math.abs(((int)x)%ref.getWidth()); + int iy = Math.abs(((int)y)%ref.getHeight()); + Color color = ref.get(ix, iy); + float[] hsv = new float[3]; + Color.RGBtoHSB(color.getRed(), color.getGreen(), color.getGreen(), hsv); + return hsv[2]; + }; + InterpolationMethod method = interpolator(rng); + int sizeMin = Math.min(image.getWidth(), image.getHeight()); + double radius = Math.max(4, rmod.fit(sizeMin / 256, sizeMin / 4, t * rng.d(0.03, 1.25), t * rng.d(0.01, 2.225))); + for(int i = 0; i < image.getWidth(); i++) + { + for(int j = 0; j < image.getHeight(); j++) + { + image.set(i, j, Color.getHSBColor( + (float)Math.max(Math.min(1D, IrisInterpolation.getNoise(method, i, j, radius, nHue)), 0D), + (float)Math.max(Math.min(1D, IrisInterpolation.getNoise(method, i, j, radius, nSat)), 0D), + (float)Math.max(Math.min(1D, IrisInterpolation.getNoise(method, i, j, radius, nBri)), 0D) + )); + } + + progressor.accept(i / (double)image.getWidth()); + } + } +} diff --git a/src/main/java/com/volmit/iris/util/uniques/features/UFNOOP.java b/src/main/java/com/volmit/iris/util/uniques/features/UFNOOP.java new file mode 100644 index 000000000..76c4db56b --- /dev/null +++ b/src/main/java/com/volmit/iris/util/uniques/features/UFNOOP.java @@ -0,0 +1,16 @@ +package com.volmit.iris.util.uniques.features; + +import com.volmit.iris.util.math.RNG; +import com.volmit.iris.util.noise.CNG; +import com.volmit.iris.util.uniques.UFeature; +import com.volmit.iris.util.uniques.UFeatureMeta; +import com.volmit.iris.util.uniques.UImage; + +import java.awt.*; +import java.util.function.Consumer; + +public class UFNOOP implements UFeature { + @Override + public void render(UImage image, RNG rng, double t, Consumer progressor, UFeatureMeta meta) { + } +} diff --git a/src/main/java/com/volmit/iris/util/uniques/features/UFWarpedBackground.java b/src/main/java/com/volmit/iris/util/uniques/features/UFWarpedBackground.java new file mode 100644 index 000000000..da5f0e411 --- /dev/null +++ b/src/main/java/com/volmit/iris/util/uniques/features/UFWarpedBackground.java @@ -0,0 +1,30 @@ +package com.volmit.iris.util.uniques.features; + +import com.volmit.iris.util.math.RNG; +import com.volmit.iris.util.noise.CNG; +import com.volmit.iris.util.uniques.UFeature; +import com.volmit.iris.util.uniques.UFeatureMeta; +import com.volmit.iris.util.uniques.UImage; + +import java.awt.*; +import java.util.function.Consumer; + +public class UFWarpedBackground implements UFeature { + @Override + public void render(UImage image, RNG rng, double t, Consumer progressor, UFeatureMeta meta) { + CNG hue = generator("color_hue", rng, rng.d(0.001, rng.d(2, 5)), rng.i(0, 3) ,rng.i(0, 3), 31007, meta); + CNG sat = generator("color_sat", rng, rng.d(0.001, rng.d(2, 5)), rng.i(0, 2) ,rng.i(0, 2), 33004, meta); + CNG bri = generator("color_bri", rng, rng.d(0.001, rng.d(2, 5)), rng.i(0, 1) ,rng.i(0, 1), 32005, meta).patch(0.145); + double tcf = rng.d(0.15, 0.55); + + for(int i = 0; i < image.getWidth(); i++) + { + for(int j = 0; j < image.getHeight(); j++) + { + image.set(i, j, color(hue, sat, bri, i, j, tcf * t)); + } + + progressor.accept(i / (double)image.getWidth()); + } + } +} diff --git a/src/main/java/com/volmit/iris/util/uniques/features/UFWarpedCircle.java b/src/main/java/com/volmit/iris/util/uniques/features/UFWarpedCircle.java new file mode 100644 index 000000000..2d73ee01b --- /dev/null +++ b/src/main/java/com/volmit/iris/util/uniques/features/UFWarpedCircle.java @@ -0,0 +1,50 @@ +package com.volmit.iris.util.uniques.features; + +import com.volmit.iris.util.math.RNG; +import com.volmit.iris.util.noise.CNG; +import com.volmit.iris.util.uniques.UFeature; +import com.volmit.iris.util.uniques.UFeatureMeta; +import com.volmit.iris.util.uniques.UImage; + +import java.awt.*; +import java.awt.image.BufferedImage; +import java.util.function.Consumer; + +public class UFWarpedCircle implements UFeature { + @Override + public void render(UImage image, RNG rng, double t, Consumer progressor, UFeatureMeta meta) { + double r = Math.min(image.getWidth(), image.getHeight()) / 2.5D; + double i, angle, x1, y1; + CNG xShift = generator("x_warp", rng, 0.6, 1001, meta); + CNG yShift = generator("y_warp", rng, 0.6, 1002, meta); + CNG hue = generator("color_hue", rng, rng.d(0.25, 2.5), 1003, meta); + CNG sat = generator("color_sat",rng, rng.d(0.25, 2.5), 1004, meta); + CNG bri = generator("color_bri",rng, rng.d(0.25, 2.5), 1005, meta); + double tcf = rng.d(0.75, 11.25); + double rcf = rng.d(7.75, 16.25); + int x = image.getWidth()/2; + int y = image.getHeight()/2; + + for(int d = 0; d < 256; d++) + { + r -= Math.min(image.getWidth(), image.getHeight()) / 300D; + + if(r <= 0) + { + return; + } + + for(i = 0; i < 360; i += 0.1) + { + angle = i; + x1 = r * Math.cos(angle * Math.PI / 180); + y1 = r * Math.sin(angle * Math.PI / 180); + image.set((int)Math.round(x + x1 + xShift.fit(-r/2, r/2, x1 + (t+ (d * 8)), -y1 + (t+ (d * 8)))), + (int)Math.round(y + y1 + yShift.fit(-r/2, r/2, y1 + (t+ (d * 8)), -x1 + (t+ (d * 8)))), + color(hue, sat, bri, x1, y1, (t * tcf) + (d * rcf))); + } + + progressor.accept(d / 256D); + } + } +} diff --git a/src/main/java/com/volmit/iris/util/uniques/features/UFWarpedDisc.java b/src/main/java/com/volmit/iris/util/uniques/features/UFWarpedDisc.java new file mode 100644 index 000000000..b394f2c7c --- /dev/null +++ b/src/main/java/com/volmit/iris/util/uniques/features/UFWarpedDisc.java @@ -0,0 +1,39 @@ +package com.volmit.iris.util.uniques.features; + +import com.volmit.iris.util.math.RNG; +import com.volmit.iris.util.noise.CNG; +import com.volmit.iris.util.uniques.UFeature; +import com.volmit.iris.util.uniques.UFeatureMeta; +import com.volmit.iris.util.uniques.UImage; + +import java.util.function.Consumer; + +public class UFWarpedDisc implements UFeature { + @Override + public void render(UImage image, RNG rng, double t, Consumer progressor, UFeatureMeta meta) { + double r = Math.min(image.getWidth(), image.getHeight()) / 3D; + CNG xShift = generator("x_warp", rng, 0.6, 1001, meta); + CNG yShift = generator("y_warp",rng, 0.6, 1002, meta); + CNG hue = generator("color_hue",rng, rng.d(0.25, 2.5), 1003, meta); + CNG sat = generator("color_sat",rng, rng.d(0.25, 2.5), 1004, meta); + CNG bri = generator("color_bri",rng, rng.d(0.25, 2.5), 1005, meta); + double tcf = rng.d(0.75, 11.25); + int x = image.getWidth()/2; + int y = image.getHeight()/2; + + for(int i = (int)( x - r); i < x+r; i++) + { + for(int j =(int)( y - r); j < y+r; j++) + { + if(image.isInBounds(i, j) && Math.pow(x - i, 2) + Math.pow(y - j, 2) <= r*r) + { + image.set(Math.round(i + xShift.fit(-r/2, r/2, i+t, -j+t)), + Math.round(j + yShift.fit(-r/2, r/2, j+t, -i+t)), + color(hue, sat, bri, i, j, tcf * t)); + } + } + + progressor.accept(i / (x + r)); + } + } +} diff --git a/src/main/java/com/volmit/iris/util/uniques/features/UFWarpedDots.java b/src/main/java/com/volmit/iris/util/uniques/features/UFWarpedDots.java new file mode 100644 index 000000000..a9670600e --- /dev/null +++ b/src/main/java/com/volmit/iris/util/uniques/features/UFWarpedDots.java @@ -0,0 +1,48 @@ +package com.volmit.iris.util.uniques.features; + +import com.volmit.iris.util.math.RNG; +import com.volmit.iris.util.noise.CNG; +import com.volmit.iris.util.uniques.UFeature; +import com.volmit.iris.util.uniques.UFeatureMeta; +import com.volmit.iris.util.uniques.UImage; + +import java.awt.*; +import java.util.function.Consumer; + +public class UFWarpedDots implements UFeature { + @Override + public void render(UImage image, RNG rng, double t, Consumer progressor, UFeatureMeta meta) { + CNG genX = generator("x_pos", rng, 4, 2000, meta); + CNG genY = generator("y_pos", rng, 4, 2001, meta); + + double tcf = rng.d(0.75, 11.25); + + for(int i = 1; i <= 8; i++) + { + CNG xShift = generator("x_warp_" + i, rng, 2, 2006+i, meta); + CNG yShift = generator("y_warp_" + i,rng, 2, 2007+i, meta); + CNG hue = generator("color_hue_" + i,rng, rng.d(0.55, 3.5), 2003+i, meta); + CNG sat = generator("color_sat_" + i,rng, rng.d(0.55, 3.5), 2004+i, meta); + CNG bri = generator("color_bri_" + i,rng, rng.d(0.55, 3.5), 2005+i, meta); + int x = genX.fit(0, image.getWidth(), i * 128, i * 5855); + int y = genY.fit(0, image.getHeight(), i * 128, i * 5855); + Color color = color(hue, sat, bri, x, y, t); + double r = Math.max(genX.fit(image.getWidth() / 10, image.getWidth() / 6, x, y), genY.fit(image.getHeight() / 10, image.getHeight() / 6, x, y)); + + for(int j = (int)(x - r); j < x + r; j++) + { + for(int k = (int)(y - r); k < y + r; k++) + { + if(image.isInBounds(j, k) && Math.pow(x - j, 2) + Math.pow(y - k, 2) <= r*r) + { + image.set(Math.round(j + xShift.fit(-r/2, r/2, j+t, -k+t)), + Math.round(k + yShift.fit(-r/2, r/2, k+t, -j+t)), + color(hue, sat, bri, j, k, tcf * t)); + } + } + } + + progressor.accept(i / 32D); + } + } +} diff --git a/src/main/java/com/volmit/iris/util/uniques/features/UFWarpedLines.java b/src/main/java/com/volmit/iris/util/uniques/features/UFWarpedLines.java new file mode 100644 index 000000000..badfdb79e --- /dev/null +++ b/src/main/java/com/volmit/iris/util/uniques/features/UFWarpedLines.java @@ -0,0 +1,47 @@ +package com.volmit.iris.util.uniques.features; + +import com.volmit.iris.util.math.RNG; +import com.volmit.iris.util.noise.CNG; +import com.volmit.iris.util.uniques.UFeature; +import com.volmit.iris.util.uniques.UFeatureMeta; +import com.volmit.iris.util.uniques.UImage; + +import java.util.function.Consumer; + +public class UFWarpedLines implements UFeature { + @Override + public void render(UImage image, RNG rng, double t, Consumer progressor, UFeatureMeta meta) { + for(int g = 1; g < 5; g++) + { + CNG xShift = generator("x_warp_"+g, rng, 0.6, 1001 * g, meta); + CNG yShift = generator("y_warp_"+g, rng, 0.6, 1002 * g, meta); + CNG cX = generator("x_clip_"+g, rng, rng.d(0.035, 0.6), 77001 * g, meta); + CNG cY = generator("y_clip"+g, rng, rng.d(0.035, 0.6), 77002, meta); + CNG hue = generator("color_hue_"+g, rng, rng.d(0.25, 2.5), 1003 * g, meta); + CNG sat = generator("color_sat_"+g, rng, rng.d(0.25, 2.5), 1004 * g, meta); + CNG bri = generator("color_bri_"+g, rng, rng.d(0.25, 2.5), 1005 * g, meta); + double tcf = rng.d(0.75, 11.25 + (g * 4)); + double rcf = rng.d(7.75, 16.25 + (g * 5)); + double xcf = rng.d(0.15, 0.55 + (g * 0.645)); + double w = rng.d(64, 186 + (g * 8)); + double ww = image.getWidth() / rng.d(3, 9); + double hh = image.getHeight() / rng.d(3, 9); + boolean wh = rng.nextBoolean(); + double sa = rng.d(0.35, 0.66); + double sb = rng.d(0.35, 0.66); + + for(int i = 0; i < image.getWidth(); i+= (wh ? image.getWidth() / w : 1)) + { + for(int j = 0; j < image.getHeight(); j+= (!wh ? image.getHeight() / w : 1)) + { + if(cX.fitDouble(0, 1, i, -j, t * xcf) > sa && cY.fitDouble(0, 1, -j, i, t * xcf) > sb) + { + image.set(Math.round(i + xShift.fit(-ww, ww, i, j, (t * rcf))), + Math.round(j + yShift.fit(-hh, hh, -j, i, (t * rcf))), + color(hue, sat, bri, i, j, (t * tcf))); + } + } + } + } + } +}