Add sphericity param to blob brush

This commit is contained in:
Jesse Boyd 2017-09-02 16:30:03 +10:00
parent 5ccb8411f3
commit 79b88cefaa
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
2 changed files with 71 additions and 23 deletions

View File

@ -1,22 +1,27 @@
package com.boydti.fawe.object.brush; package com.boydti.fawe.object.brush;
import com.boydti.fawe.object.random.SimplexNoise; import com.boydti.fawe.object.random.SimplexNoise;
import com.boydti.fawe.util.MathMan;
import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.MutableBlockVector;
import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.command.tool.brush.Brush; import com.sk89q.worldedit.command.tool.brush.Brush;
import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.math.transform.AffineTransform;
import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.ThreadLocalRandom;
public class BlobBrush implements Brush { public class BlobBrush implements Brush {
private final double amplitude; private final double amplitude;
private final double frequency; private final double frequency;
private final Vector radius; 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.frequency = frequency;
this.amplitude = amplitude; this.amplitude = amplitude;
this.radius = radius; this.radius = radius;
this.sphericity = sphericity;
} }
@Override @Override
@ -31,12 +36,14 @@ public class BlobBrush implements Brush {
double distort = this.frequency / size; double distort = this.frequency / size;
double modX = 1d/radius.getX(); double modX = 1d / radius.getX();
double modY = 1d/radius.getY(); double modY = 1d / radius.getY();
double modZ = 1d/radius.getZ(); double modZ = 1d / radius.getZ();
int radius = (int) size;
int radiusSqr = (int) (size * size); int radiusSqr = (int) (size * size);
int sizeInt = (int) size * 2; int sizeInt = (int) size * 2;
if (sphericity == 1) {
for (int x = -sizeInt; x <= sizeInt; x++) { for (int x = -sizeInt; x <= sizeInt; x++) {
double nx = seedX + x * distort; double nx = seedX + x * distort;
double d1 = x * x * modX; double d1 = x * x * modX;
@ -53,5 +60,46 @@ public class BlobBrush implements Brush {
} }
} }
} }
} 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);
}
}
}
}
}
} }
} }

View File

@ -289,18 +289,18 @@ public class BrushCommands extends MethodCommands {
} }
@Command( @Command(
aliases = {"blob", "rock"}, aliases = {"rock", "blob"},
usage = "<pattern> [radius=10] [frequency=30] [amplitude=50]", usage = "<pattern> [radius=10] [roundness=100] [frequency=30] [amplitude=50]",
flags = "h", flags = "h",
desc = "Creates a distorted sphere", desc = "Creates a distorted sphere",
min = 1, min = 1,
max = 4 max = 5
) )
@CommandPermissions("worldedit.brush.blob") @CommandPermissions("worldedit.brush.rock")
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 { 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()); double max = MathMan.max(radius.getBlockX(), radius.getBlockY(), radius.getBlockZ());
worldEdit.checkMaxBrushRadius(max); 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) return get(context)
.setBrush(brush) .setBrush(brush)
.setSize(max) .setSize(max)