Skip to content

Commit 2b16594

Browse files
committed
Add rotation options to noise pattern
1 parent ecd3c89 commit 2b16594

File tree

1 file changed

+91
-12
lines changed

1 file changed

+91
-12
lines changed

src/main/java/heronarts/lx/pattern/texture/NoisePattern.java

Lines changed: 91 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import heronarts.lx.parameter.FunctionalParameter;
3535
import heronarts.lx.parameter.LXParameter;
3636
import heronarts.lx.pattern.LXPattern;
37+
import heronarts.lx.transform.LXParameterizedMatrix;
3738
import heronarts.lx.utils.LXUtils;
3839

3940
import static heronarts.lx.utils.Noise.*;
@@ -265,6 +266,30 @@ public double getValue() {
265266
new BoundedParameter("Ridge", .9, 0, 2)
266267
.setDescription("Used to invert the feedback ridges");
267268

269+
public final BooleanParameter rotate =
270+
new BooleanParameter("Rotate", false)
271+
.setDescription("Whether to rotate the geometry");
272+
273+
public final CompoundParameter yaw =
274+
new CompoundParameter("Yaw", 0, 360)
275+
.setWrappable(true)
276+
.setUnits(CompoundParameter.Units.DEGREES)
277+
.setDescription("Yaw rotation");
278+
279+
public final CompoundParameter pitch =
280+
new CompoundParameter("Pitch", 0, 360)
281+
.setWrappable(true)
282+
.setUnits(CompoundParameter.Units.DEGREES)
283+
.setDescription("Pitch rotation");
284+
285+
public final CompoundParameter roll =
286+
new CompoundParameter("Roll", 0, 360)
287+
.setWrappable(true)
288+
.setUnits(CompoundParameter.Units.DEGREES)
289+
.setDescription("Roll rotation");
290+
291+
private final LXParameterizedMatrix transform = new LXParameterizedMatrix();
292+
268293
private final GradientUtils.GrayTable invertLUT = new GradientUtils.GrayTable(this.invert, 256);
269294

270295
public NoisePattern(LX lx) {
@@ -305,6 +330,11 @@ public NoisePattern(LX lx) {
305330
addParameter("yMode", this.yMode);
306331
addParameter("zMode", this.zMode);
307332

333+
addTransformParameter("rotate", this.rotate);
334+
addTransformParameter("yaw", this.yaw);
335+
addTransformParameter("pitch", this.pitch);
336+
addTransformParameter("roll", this.roll);
337+
308338
// Set the order of most useful control parameters
309339
setRemoteControls(
310340
this.scale,
@@ -324,6 +354,11 @@ public NoisePattern(LX lx) {
324354
);
325355
}
326356

357+
private void addTransformParameter(String key, LXParameter parameter) {
358+
addParameter(key, parameter);
359+
this.transform.addParameter(parameter);
360+
}
361+
327362
@Override
328363
public void onParameterChanged(LXParameter p) {
329364
super.onParameterChanged(p);
@@ -340,6 +375,17 @@ public void onParameterChanged(LXParameter p) {
340375
public void run(double deltaMs) {
341376
this.invertLUT.update();
342377

378+
if (this.rotate.isOn()) {
379+
this.transform.update(matrix -> {
380+
matrix
381+
.translate(.5f, .5f, .5f)
382+
.rotateZ((float) Math.toRadians(-this.roll.getValue()))
383+
.rotateX((float) Math.toRadians(-this.pitch.getValue()))
384+
.rotateY((float) Math.toRadians(-this.yaw.getValue()))
385+
.translate(-.5f, -.5f, -.5f);
386+
});
387+
}
388+
343389
switch (this.algorithm.getEnum()) {
344390
case PERLIN:
345391
case FBM:
@@ -353,6 +399,37 @@ public void run(double deltaMs) {
353399
}
354400
}
355401

402+
private interface CoordinateAccessor {
403+
404+
public float xn(LXPoint p);
405+
public float yn(LXPoint p);
406+
public float zn(LXPoint p);
407+
408+
static final CoordinateAccessor RAW = new CoordinateAccessor() {
409+
public float xn(LXPoint p) {
410+
return p.xn;
411+
}
412+
public float yn(LXPoint p) {
413+
return p.yn;
414+
}
415+
public float zn(LXPoint p) {
416+
return p.zn;
417+
}
418+
};
419+
}
420+
421+
private final CoordinateAccessor TRANSFORM = new CoordinateAccessor() {
422+
public float xn(LXPoint p) {
423+
return transform.xn(p);
424+
}
425+
public float yn(LXPoint p) {
426+
return transform.yn(p);
427+
}
428+
public float zn(LXPoint p) {
429+
return transform.zn(p);
430+
}
431+
};
432+
356433
private void runPerlin(double deltaMs, Algorithm algorithm) {
357434
final int seed = this.seed.getValuei();
358435

@@ -375,15 +452,17 @@ private void runPerlin(double deltaMs, Algorithm algorithm) {
375452
final float maxLevel = this.maxLevel.getValuef();
376453
final float level = LXUtils.lerpf(minLevel, maxLevel, (this.level.getValuef() - contrast / 4) * .01f);
377454

455+
final CoordinateAccessor coord = this.rotate.isOn() ? TRANSFORM : CoordinateAccessor.RAW;
456+
378457
final CoordinateFunction xMode = this.xMode.getEnum().function;
379458
final CoordinateFunction yMode = this.yMode.getEnum().function;
380459
final CoordinateFunction zMode = this.zMode.getEnum().function;
381460

382461
if (algorithm.equals(Algorithm.PERLIN)) {
383462
for (LXPoint p : model.points) {
384-
float xd = xMode.getCoordinate(p, p.xn, xo);
385-
float yd = yMode.getCoordinate(p, p.yn, yo);
386-
float zd = zMode.getCoordinate(p, p.zn, zo);
463+
float xd = xMode.getCoordinate(p, coord.xn(p), xo);
464+
float yd = yMode.getCoordinate(p, coord.yn(p), yo);
465+
float zd = zMode.getCoordinate(p, coord.zn(p), zo);
387466

388467
float b = level + contrast * stb_perlin_noise3_seed(xa + xs * xd, ya + ys * yd, za + zs * zd, 0, 0, 0, seed);
389468
this.colors[p.index] = this.invertLUT.lut[(int) (2.559 * clamp(b, minLevel, maxLevel))];
@@ -396,25 +475,25 @@ private void runPerlin(double deltaMs, Algorithm algorithm) {
396475
if (algorithm.equals(Algorithm.RIDGE)) {
397476
float ridgeOffset = this.ridgeOffset.getValuef();
398477
for (LXPoint p : model.points) {
399-
float xd = xMode.getCoordinate(p, p.xn, xo);
400-
float yd = yMode.getCoordinate(p, p.yn, yo);
401-
float zd = zMode.getCoordinate(p, p.zn, zo);
478+
float xd = xMode.getCoordinate(p, coord.xn(p), xo);
479+
float yd = yMode.getCoordinate(p, coord.yn(p), yo);
480+
float zd = zMode.getCoordinate(p, coord.zn(p), zo);
402481
float b = level + contrast * stb_perlin_ridge_noise3(xa + xs * xd, ya + ys * yd, za + zs * zd, lacunarity, gain, ridgeOffset, octaves);
403482
this.colors[p.index] = this.invertLUT.lut[(int) (2.559 * clamp(b, minLevel, maxLevel))];
404483
}
405484
} else if (algorithm.equals(Algorithm.FBM)) {
406485
for (LXPoint p : model.points) {
407-
float xd = xMode.getCoordinate(p, p.xn, xo);
408-
float yd = yMode.getCoordinate(p, p.yn, yo);
409-
float zd = zMode.getCoordinate(p, p.zn, zo);
486+
float xd = xMode.getCoordinate(p, coord.xn(p), xo);
487+
float yd = yMode.getCoordinate(p, coord.yn(p), yo);
488+
float zd = zMode.getCoordinate(p, coord.zn(p), zo);
410489
float b = level + contrast * stb_perlin_fbm_noise3(xa + xs * xd, ya + ys * yd, za + zs * zd, lacunarity, gain, octaves);
411490
this.colors[p.index] = this.invertLUT.lut[(int) (2.559 * clamp(b, minLevel, maxLevel))];
412491
}
413492
} else if (algorithm.equals(Algorithm.TURBULENCE)) {
414493
for (LXPoint p : model.points) {
415-
float xd = xMode.getCoordinate(p, p.xn, xo);
416-
float yd = yMode.getCoordinate(p, p.yn, yo);
417-
float zd = zMode.getCoordinate(p, p.zn, zo);
494+
float xd = xMode.getCoordinate(p, coord.xn(p), xo);
495+
float yd = yMode.getCoordinate(p, coord.yn(p), yo);
496+
float zd = zMode.getCoordinate(p, coord.zn(p), zo);
418497
float b = level + contrast * stb_perlin_turbulence_noise3(xa + xs * xd, ya + ys * yd, za + zs * zd, lacunarity, gain, octaves);
419498
this.colors[p.index] = this.invertLUT.lut[(int) (2.559 * clamp(b, minLevel, maxLevel))];
420499
}

0 commit comments

Comments
 (0)