From 79b88cefaa7e89489934709032b8dd242e3e6a02 Mon Sep 17 00:00:00 2001 From: Jesse Boyd Date: Sat, 2 Sep 2017 16:30:03 +1000 Subject: [PATCH] Add sphericity param to blob brush --- .../boydti/fawe/object/brush/BlobBrush.java | 82 +++++++++++++++---- .../worldedit/command/BrushCommands.java | 12 +-- 2 files changed, 71 insertions(+), 23 deletions(-) diff --git a/core/src/main/java/com/boydti/fawe/object/brush/BlobBrush.java b/core/src/main/java/com/boydti/fawe/object/brush/BlobBrush.java index 35c4a53e..5e32fa45 100644 --- a/core/src/main/java/com/boydti/fawe/object/brush/BlobBrush.java +++ b/core/src/main/java/com/boydti/fawe/object/brush/BlobBrush.java @@ -1,22 +1,27 @@ package com.boydti.fawe.object.brush; import com.boydti.fawe.object.random.SimplexNoise; +import com.boydti.fawe.util.MathMan; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.MaxChangedBlocksException; +import com.sk89q.worldedit.MutableBlockVector; import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.command.tool.brush.Brush; import com.sk89q.worldedit.function.pattern.Pattern; +import com.sk89q.worldedit.math.transform.AffineTransform; import java.util.concurrent.ThreadLocalRandom; public class BlobBrush implements Brush { private final double amplitude; private final double frequency; private final Vector radius; + private final double sphericity; - public BlobBrush(Vector radius, double frequency, double amplitude) { + public BlobBrush(Vector radius, double frequency, double amplitude, double sphericity) { this.frequency = frequency; this.amplitude = amplitude; this.radius = radius; + this.sphericity = sphericity; } @Override @@ -31,24 +36,67 @@ public class BlobBrush implements Brush { double distort = this.frequency / size; - double modX = 1d/radius.getX(); - double modY = 1d/radius.getY(); - double modZ = 1d/radius.getZ(); - + double modX = 1d / radius.getX(); + double modY = 1d / radius.getY(); + double modZ = 1d / radius.getZ(); + int radius = (int) size; int radiusSqr = (int) (size * size); int sizeInt = (int) size * 2; - for (int x = -sizeInt; x <= sizeInt; x++) { - double nx = seedX + x * distort; - double d1 = x * x * modX; - for (int y = -sizeInt; y <= sizeInt; y++) { - double d2 = d1 + y * y * modY; - double ny = seedY + y * distort; - for (int z = -sizeInt; z <= sizeInt; z++) { - double nz = seedZ + z * distort; - double distance = d2 + z * z * modZ; - double noise = this.amplitude * SimplexNoise.noise(nx, ny, nz); - if (distance + distance * noise < radiusSqr) { - editSession.setBlock(px + x, py + y, pz + z, pattern); + + if (sphericity == 1) { + for (int x = -sizeInt; x <= sizeInt; x++) { + double nx = seedX + x * distort; + double d1 = x * x * modX; + for (int y = -sizeInt; y <= sizeInt; y++) { + double d2 = d1 + y * y * modY; + double ny = seedY + y * distort; + for (int z = -sizeInt; z <= sizeInt; z++) { + double nz = seedZ + z * distort; + double distance = d2 + z * z * modZ; + double noise = this.amplitude * SimplexNoise.noise(nx, ny, nz); + if (distance + distance * noise < radiusSqr) { + editSession.setBlock(px + x, py + y, pz + z, pattern); + } + } + } + } + } else { + AffineTransform transform = new AffineTransform() + .rotateX(ThreadLocalRandom.current().nextInt(360)) + .rotateY(ThreadLocalRandom.current().nextInt(360)) + .rotateZ(ThreadLocalRandom.current().nextInt(360)); + + double manScaleX = (1.25 + seedX * 0.5); + double manScaleY = (1.25 + seedY * 0.5); + double manScaleZ = (1.25 + seedZ * 0.5); + + MutableBlockVector mutable = new MutableBlockVector(); + double roughness = 1 - sphericity; + for (int xr = -sizeInt; xr <= sizeInt; xr++) { + mutable.mutX(xr); + for (int yr = -sizeInt; yr <= sizeInt; yr++) { + mutable.mutY(yr); + for (int zr = -sizeInt; zr <= sizeInt; zr++) { + mutable.mutZ(zr); + Vector pt = transform.apply(mutable); + int x = MathMan.roundInt(pt.getBlockX()); + int y = MathMan.roundInt(pt.getBlockY()); + int z = MathMan.roundInt(pt.getBlockZ()); + + double xScaled = Math.abs(x) * modX; + double yScaled = Math.abs(y) * modY; + double zScaled = Math.abs(z) * modZ; + double manDist = xScaled + yScaled + zScaled; + double distSqr = x * x * modX + z * z * modZ + y * y * modY; + + double distance = + Math.sqrt(distSqr) * sphericity + + MathMan.max(manDist, xScaled * manScaleX, yScaled * manScaleY, zScaled * manScaleZ) * roughness; + + double noise = this.amplitude * SimplexNoise.noise(seedX + x * distort, seedZ + z * distort, seedZ + z * distort); + if (distance + distance * noise < radius) { + editSession.setBlock(px + xr, py + yr, pz + zr, pattern); + } } } } diff --git a/core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java b/core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java index 8b868c7f..5aa82e04 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java +++ b/core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java @@ -289,18 +289,18 @@ public class BrushCommands extends MethodCommands { } @Command( - aliases = {"blob", "rock"}, - usage = " [radius=10] [frequency=30] [amplitude=50]", + aliases = {"rock", "blob"}, + usage = " [radius=10] [roundness=100] [frequency=30] [amplitude=50]", flags = "h", desc = "Creates a distorted sphere", min = 1, - max = 4 + max = 5 ) - @CommandPermissions("worldedit.brush.blob") - public BrushSettings blobBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("10") Vector radius, @Optional("30") double frequency, @Optional("50") double amplitude, CommandContext context) throws WorldEditException { + @CommandPermissions("worldedit.brush.rock") + public BrushSettings blobBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("10") Vector radius, @Optional("100") double sphericity, @Optional("30") double frequency, @Optional("50") double amplitude, CommandContext context) throws WorldEditException { double max = MathMan.max(radius.getBlockX(), radius.getBlockY(), radius.getBlockZ()); worldEdit.checkMaxBrushRadius(max); - Brush brush = new BlobBrush(radius.divide(max), frequency / 100, amplitude / 100); + Brush brush = new BlobBrush(radius.divide(max), frequency / 100, amplitude / 100, sphericity / 100); return get(context) .setBrush(brush) .setSize(max)