From 0bf6c885fdaa8273ab72789f7efcd9477234168a Mon Sep 17 00:00:00 2001 From: =?utf8?q?Tomas=20Wenstr=C3=B6m?= Date: Mon, 24 Apr 2017 21:23:46 +0200 Subject: [PATCH] New ambient mode --- src/kaka/cakelight/AmbientMode.java | 27 ++++++-- src/kaka/cakelight/LedFrame.java | 19 ++++++ src/kaka/cakelight/Main.java | 2 +- src/kaka/cakelight/util/SimplexNoise3D.java | 97 +++++++++++++++++++++++++++++ 4 files changed, 140 insertions(+), 5 deletions(-) create mode 100644 src/kaka/cakelight/util/SimplexNoise3D.java diff --git a/src/kaka/cakelight/AmbientMode.java b/src/kaka/cakelight/AmbientMode.java index 51cb1e6..a6ae8da 100644 --- a/src/kaka/cakelight/AmbientMode.java +++ b/src/kaka/cakelight/AmbientMode.java @@ -1,8 +1,17 @@ package kaka.cakelight; +import kaka.cakelight.util.SimplexNoise3D; + public class AmbientMode extends Mode { // TODO split into DynamicAmbient and StaticAmbient? private Thread thread; // TODO move to a dynamic sub class private Configuration config; + private int type = 0; + + public AmbientMode(String[] args) { + if (args.length > 0) { + type = Integer.parseInt(args[0]); + } + } @Override public void enter(Configuration config) { @@ -45,10 +54,20 @@ public class AmbientMode extends Mode { // TODO split into DynamicAmbient and St * @param count Goes from 0 to number of LEDs - 1 */ private void updateFrame(LedFrame frame, long time, int count) { - for (int i = 0; i < config.leds.getCount(); i++) { - double r = Math.sin(2 * i * Math.PI / config.leds.getCount() + time * 0.001) * 0.5 + 0.5; - double g = Math.cos(2 * i * Math.PI / config.leds.getCount() + time * 0.002) * 0.5 + 0.5; - frame.setLedColor(i, Color.rgb(r, g, 0)); + if (type == 0) { + for (int i = 0; i < config.leds.getCount(); i++) { + double r = Math.sin(2 * i * Math.PI / config.leds.getCount() + time * 0.001) * 0.5 + 0.5; + double g = Math.cos(2 * i * Math.PI / config.leds.getCount() + time * 0.002) * 0.5 + 0.5; + frame.setLedColor(i, Color.rgb(r, g, 0)); + } + } else if (type == 1) { + for (int i = 0; i < config.leds.getCount(); i++) { + double g = noise.getr(0, 0.5, 0.5, frame.xOf(i), frame.yOf(i), time / 5000.0); + double b = noise.getr(0, 1, 1, frame.xOf(i), frame.yOf(i), time / 7000.0); + frame.setLedColor(i, Color.rgb(0, g, b)); + } } } + + private SimplexNoise3D noise = new SimplexNoise3D(0); } diff --git a/src/kaka/cakelight/LedFrame.java b/src/kaka/cakelight/LedFrame.java index 4d6b68a..9d95b0c 100644 --- a/src/kaka/cakelight/LedFrame.java +++ b/src/kaka/cakelight/LedFrame.java @@ -1,11 +1,13 @@ package kaka.cakelight; public class LedFrame { + private Configuration config; private byte[] bytes; private int roff = 0, goff = 2, boff = 1; // Color values are stored as RBG, which is what the LED list takes. public static LedFrame from(Configuration config) { LedFrame frame = new LedFrame(); + frame.config = config; frame.bytes = new byte[config.leds.getCount() * 3]; return frame; } @@ -41,4 +43,21 @@ public class LedFrame { public byte[] getBytes() { return bytes; } + + // TODO this needs to be improved + /** The x position of the led from 0.0-1.0. */ + public double xOf(int led) { + /* left */ if (led >= config.leds.cols * 2 + config.leds.rows) return 0; + /* top */ if (led >= config.leds.cols + config.leds.rows) return 1 - (double)(led - config.leds.cols - config.leds.rows) / config.leds.cols; + /* right */ if (led >= config.leds.cols) return 1; + /* bottom */ return (double)led / config.leds.cols; + } + + /** The y position of the led from 0.0-1.0. */ + public double yOf(int led) { + /* left */ if (led >= config.leds.cols * 2 + config.leds.rows) return (double)(led - config.leds.cols * 2 - config.leds.rows) / config.leds.rows; + /* top */ if (led >= config.leds.cols + config.leds.rows) return 0; + /* right */ if (led >= config.leds.cols) return 1 - (double)(led - config.leds.cols) / config.leds.rows; + /* bottom */ return 1; + } } diff --git a/src/kaka/cakelight/Main.java b/src/kaka/cakelight/Main.java index 52d3b61..59e03ff 100644 --- a/src/kaka/cakelight/Main.java +++ b/src/kaka/cakelight/Main.java @@ -14,7 +14,7 @@ public class Main { log("Running with config:\n" + config); CakeLight cakelight = new CakeLight(config, new LedController(config)); - cakelight.setMode(new AmbientMode()); + cakelight.setMode(new AmbientMode(args)); cakelight.startLoop(); Runtime.getRuntime().addShutdownHook(new Thread(Main::printTimeStats)); } diff --git a/src/kaka/cakelight/util/SimplexNoise3D.java b/src/kaka/cakelight/util/SimplexNoise3D.java new file mode 100644 index 0000000..7749acc --- /dev/null +++ b/src/kaka/cakelight/util/SimplexNoise3D.java @@ -0,0 +1,97 @@ +package kaka.cakelight.util; + +import java.util.Random; + +import static java.lang.Math.*; + +public class SimplexNoise3D { + private final byte[] ptab = new byte[256]; + private final double[][] gtab = { + { 1, 1, 0}, {-1, 1, 0}, { 1, -1, 0}, {-1, -1, 0}, + { 1, 0, 1}, {-1, 0, 1}, { 1, 0, -1}, {-1, 0, -1}, + { 0, 1, 1}, { 0, -1, 1}, { 0, 1, -1}, { 0, -1, -1}, + }; + + public SimplexNoise3D(Random rnd) { + for(int i = 0; i < 256; i++) + ptab[i] = (byte)i; + for(int i = 0; i < 256; i++) { + int r = rnd.nextInt(256); + byte t = ptab[i]; ptab[i] = ptab[r]; ptab[r] = t; + } + } + + public SimplexNoise3D(long seed) { + this(new Random(seed)); + } + + public SimplexNoise3D() { + this(new Random()); + } + + public double get(double r, double x, double y, double z) { + x /= r; y /= r; z /= r; + + double i, j, k; + { + double s = (x + y + z) / 3; + i = floor(x + s); + j = floor(y + s); + k = floor(z + s); + } + + double dx, dy, dz; + { + double s = (i + j + k) / 6; + dx = x - (i - s); + dy = y - (j - s); + dz = z - (k - s); + } + + int i1, j1, k1, i2, j2, k2; + if((dx >= dy) && (dy >= dz)) { + i1 = 1; j1 = 0; k1 = 0; i2 = 1; j2 = 1; k2 = 0; + } else if((dx >= dz) && (dz >= dy)) { + i1 = 1; j1 = 0; k1 = 0; i2 = 1; j2 = 0; k2 = 1; + } else if((dz >= dx) && (dx >= dy)) { + i1 = 0; j1 = 0; k1 = 1; i2 = 1; j2 = 0; k2 = 1; + } else if((dz >= dy) && (dy >= dx)) { + i1 = 0; j1 = 0; k1 = 1; i2 = 0; j2 = 1; k2 = 1; + } else if((dy >= dz) && (dz >= dx)) { + i1 = 0; j1 = 1; k1 = 0; i2 = 0; j2 = 1; k2 = 1; + } else /* if((dy >= dx) && (dx >= dz)) */ { + i1 = 0; j1 = 1; k1 = 0; i2 = 1; j2 = 1; k2 = 0; + } + + double x1 = dx - i1 + (1.0 / 6.0), y1 = dy - j1 + (1.0 / 6.0), z1 = dz - k1 + (1.0 / 6.0); + double x2 = dx - i2 + (1.0 / 3.0), y2 = dy - j2 + (1.0 / 3.0), z2 = dz - k2 + (1.0 / 3.0); + double x3 = dx - 0.5, y3 = dy - 0.5, z3 = dz - 0.5; + + int ip = (int)i, jp = (int)j, kp = (int)k; + double[] g0 = gtab[((int)ptab[(int)(ip + ptab[(int)(jp + ptab[(int)kp & 0xff]) & 0xff]) & 0xff] & 0xff) % 12]; + double[] g1 = gtab[((int)ptab[(int)(ip + i1 + ptab[(int)(jp + j1 + ptab[(int)(kp + k1) & 0xff]) & 0xff]) & 0xff] & 0xff) % 12]; + double[] g2 = gtab[((int)ptab[(int)(ip + i2 + ptab[(int)(jp + j2 + ptab[(int)(kp + k2) & 0xff]) & 0xff]) & 0xff] & 0xff) % 12]; + double[] g3 = gtab[((int)ptab[(int)(ip + 1 + ptab[(int)(jp + 1 + ptab[(int)(kp + 1) & 0xff]) & 0xff]) & 0xff] & 0xff) % 12]; + + double n0 = 0.6 - (dx * dx) - (dy * dy) - (dz * dz); + double n1 = 0.6 - (x1 * x1) - (y1 * y1) - (z1 * z1); + double n2 = 0.6 - (x2 * x2) - (y2 * y2) - (z2 * z2); + double n3 = 0.6 - (x3 * x3) - (y3 * y3) - (z3 * z3); + + double v = 0.0; + if(n0 > 0) v += n0 * n0 * n0 * n0 * ((g0[0] * dx) + (g0[1] * dy) + (g0[2] * dz)); + if(n1 > 0) v += n1 * n1 * n1 * n1 * ((g1[0] * x1) + (g1[1] * y1) + (g1[2] * z1)); + if(n2 > 0) v += n2 * n2 * n2 * n2 * ((g2[0] * x2) + (g2[1] * y2) + (g2[2] * z2)); + if(n3 > 0) v += n3 * n3 * n3 * n3 * ((g3[0] * x3) + (g3[1] * y3) + (g3[2] * z3)); + + return(min(max(v * 32, -1.0), 1.0)); + } + + public double getr(double lo, double hi, double r, double x, double y, double z) { + return((((get(r, x, y, z) * 0.5) + 0.5) * (hi - lo)) + lo); + } + + public int geti(int lo, int hi, double r, double x, double y, double z) { + return(min((int)(((get(r, x, y, z) * 0.5) + 0.5) * (hi - lo)), (int)((hi - lo) - 1)) + lo); + } +} -- 2.11.0