From b7e9547cd544cd7cc18c336bb44c5e857cef45e0 Mon Sep 17 00:00:00 2001 From: Hazel Trinity Date: Fri, 14 Aug 2020 19:04:11 -0700 Subject: [PATCH 01/10] Fixed NullPointerException in Spline and Sweep brush --- .../java/com/boydti/fawe/object/brush/sweep/SweepBrush.java | 2 +- .../main/java/com/boydti/fawe/object/visitor/DFSVisitor.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/sweep/SweepBrush.java b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/sweep/SweepBrush.java index e2d05508f..f8b387512 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/sweep/SweepBrush.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/sweep/SweepBrush.java @@ -46,7 +46,7 @@ public class SweepBrush implements Brush, ResettableTool { return; } - boolean newPos = !position.equals(this.position); + boolean newPos = this.position == null || !position.equals(this.position); this.position = position; Player player = editSession.getPlayer(); if (player == null) { diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/visitor/DFSVisitor.java b/worldedit-core/src/main/java/com/boydti/fawe/object/visitor/DFSVisitor.java index 152e0ef4e..4d2d8861f 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/visitor/DFSVisitor.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/visitor/DFSVisitor.java @@ -104,7 +104,7 @@ public abstract class DFSVisitor implements Operation { from.getZ() + direction.getZ()); if (isVisitable(bv, bv2)) { Node adjacent = new Node(bv2.getBlockX(), bv2.getBlockY(), bv2.getBlockZ()); - if (!adjacent.equals(current.from)) { + if (current.from == null || !adjacent.equals(current.from)) { AtomicInteger adjacentCount = visited.get(adjacent); if (adjacentCount == null) { if (countAdd++ < maxBranch) { From da9c4ad543ead33b41d64057b1a9b5b3bedde844 Mon Sep 17 00:00:00 2001 From: Hazel Trinity Date: Sat, 15 Aug 2020 09:21:33 -0700 Subject: [PATCH 02/10] Handle null case in equality checking BlockVector3+DFSNode --- .../main/java/com/boydti/fawe/object/brush/SplineBrush.java | 2 +- .../java/com/boydti/fawe/object/brush/sweep/SweepBrush.java | 2 +- .../java/com/boydti/fawe/object/visitor/DFSVisitor.java | 6 +++++- .../main/java/com/sk89q/worldedit/math/BlockVector3.java | 4 ++++ .../worldedit/regions/selector/CuboidRegionSelector.java | 4 ++-- .../regions/selector/ExtendingCuboidRegionSelector.java | 2 +- 6 files changed, 14 insertions(+), 6 deletions(-) diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/SplineBrush.java b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/SplineBrush.java index aa1151639..9e750d140 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/SplineBrush.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/SplineBrush.java @@ -59,7 +59,7 @@ public class SplineBrush implements Brush, ResettableTool { return; } int originalSize = numSplines; - boolean newPos = this.position == null || !position.equals(this.position); + boolean newPos = !position.equals(this.position); this.position = position; if (newPos) { if (positionSets.size() >= MAX_POINTS) { diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/sweep/SweepBrush.java b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/sweep/SweepBrush.java index f8b387512..e2d05508f 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/sweep/SweepBrush.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/sweep/SweepBrush.java @@ -46,7 +46,7 @@ public class SweepBrush implements Brush, ResettableTool { return; } - boolean newPos = this.position == null || !position.equals(this.position); + boolean newPos = !position.equals(this.position); this.position = position; Player player = editSession.getPlayer(); if (player == null) { diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/visitor/DFSVisitor.java b/worldedit-core/src/main/java/com/boydti/fawe/object/visitor/DFSVisitor.java index 4d2d8861f..5d6b9d05d 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/visitor/DFSVisitor.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/visitor/DFSVisitor.java @@ -104,7 +104,7 @@ public abstract class DFSVisitor implements Operation { from.getZ() + direction.getZ()); if (isVisitable(bv, bv2)) { Node adjacent = new Node(bv2.getBlockX(), bv2.getBlockY(), bv2.getBlockZ()); - if (current.from == null || !adjacent.equals(current.from)) { + if (!adjacent.equals(current.from)) { AtomicInteger adjacentCount = visited.get(adjacent); if (adjacentCount == null) { if (countAdd++ < maxBranch) { @@ -200,6 +200,10 @@ public abstract class DFSVisitor implements Operation { @Override public boolean equals(Object obj) { + if (obj == null) { + return false; + } + Node other = (Node) obj; return other.x == x && other.z == z && other.y == y; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/math/BlockVector3.java b/worldedit-core/src/main/java/com/sk89q/worldedit/math/BlockVector3.java index 6656bf67a..49cd531c5 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/math/BlockVector3.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/math/BlockVector3.java @@ -775,6 +775,10 @@ public abstract class BlockVector3 { } public final boolean equals(BlockVector3 other) { + if (other == null) { + return false; + } + return other.getX() == this.getX() && other.getY() == this.getY() && other.getZ() == this.getZ(); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/CuboidRegionSelector.java b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/CuboidRegionSelector.java index 003ba8a7c..47f22c27d 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/CuboidRegionSelector.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/CuboidRegionSelector.java @@ -128,7 +128,7 @@ public class CuboidRegionSelector implements RegionSelector, CUIRegion { public boolean selectPrimary(BlockVector3 position, SelectorLimits limits) { checkNotNull(position); - if (position1 != null && position.equals(position1)) { + if (position.equals(position1)) { return false; } @@ -141,7 +141,7 @@ public class CuboidRegionSelector implements RegionSelector, CUIRegion { public boolean selectSecondary(BlockVector3 position, SelectorLimits limits) { checkNotNull(position); - if (position2 != null && position.equals(position2)) { + if (position.equals(position2)) { return false; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/ExtendingCuboidRegionSelector.java b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/ExtendingCuboidRegionSelector.java index 7a8c7b2ec..606603709 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/ExtendingCuboidRegionSelector.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/ExtendingCuboidRegionSelector.java @@ -87,7 +87,7 @@ public class ExtendingCuboidRegionSelector extends CuboidRegionSelector { @Override public boolean selectPrimary(BlockVector3 position, SelectorLimits limits) { - if (position1 != null && position2 != null && position.equals(position1) && position.equals(position2)) { + if (position.equals(position1) && position.equals(position2)) { return false; } From e51f6e562de67ee5033c43eb32063e5d3b76b079 Mon Sep 17 00:00:00 2001 From: Hazel Trinity Date: Sat, 15 Aug 2020 14:20:47 -0700 Subject: [PATCH 03/10] Sweep brush semi-fix --- .../fawe/object/brush/sweep/Spline.java | 2 +- .../fawe/object/brush/sweep/SweepBrush.java | 46 ++++++++++++++----- .../math/transform/RoundedTransform.java | 3 +- 3 files changed, 37 insertions(+), 14 deletions(-) diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/sweep/Spline.java b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/sweep/Spline.java index b7f2eafe4..d8aaf070b 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/sweep/Spline.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/sweep/Spline.java @@ -129,7 +129,7 @@ public abstract class Spline { // Calculate position from spline BlockVector3 target = interpolation.getPosition(position).toBlockPoint(); BlockVector3 offset = target.subtract(target.round()); - target = target.subtract(offset); + target = target.subtract(offset).round(); // Calculate rotation from spline diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/sweep/SweepBrush.java b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/sweep/SweepBrush.java index e2d05508f..250d2e956 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/sweep/SweepBrush.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/sweep/SweepBrush.java @@ -13,11 +13,13 @@ import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.MutableVector3; +import com.sk89q.worldedit.math.Vector2; import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.math.interpolation.Interpolation; import com.sk89q.worldedit.math.interpolation.KochanekBartelsInterpolation; import com.sk89q.worldedit.math.interpolation.Node; import com.sk89q.worldedit.math.transform.AffineTransform; +import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.session.ClipboardHolder; import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; @@ -39,6 +41,22 @@ public class SweepBrush implements Brush, ResettableTool { this.copies = copies > 0 ? copies : -1; } + private Vector3 getSidePos(Interpolation interpol, double position, Clipboard clipboard, boolean rightHand) { + Vector3 pos = interpol.getPosition(position); + Vector3 deriv = interpol.get1stDerivative(position); + double length = (rightHand ? 1 : -1) * Math.abs( + clipboard.getOrigin().getBlockZ() - clipboard.getRegion().getMinimumPoint().getBlockZ() + ); + + Vector3 cross = deriv.cross(Vector3.UNIT_Y); + if (cross.equals(Vector3.ZERO)) { + return null; + } + + Vector3 perpendicular = cross.normalize().multiply(length); + return pos.add(perpendicular); + } + @Override public void build(EditSession editSession, BlockVector3 position, Pattern pattern, double size) throws MaxChangedBlocksException { boolean visualization = editSession.getExtent() instanceof VisualExtent; @@ -99,18 +117,24 @@ public class SweepBrush implements Brush, ResettableTool { double splineLength = interpol.arcLength(0D, 1D); double blockDistance = 1d / splineLength; double step = blockDistance / quality; - double accumulation = 0; - MutableVector3 last = new MutableVector3(0, 0, 0); + MutableVector3 lastLHS = new MutableVector3(getSidePos(interpol, 0, clipboard, false).round()); + MutableVector3 lastRHS = new MutableVector3(getSidePos(interpol, 0, clipboard, true).round()); + for (double pos = 0D; pos <= 1D; pos += step) { - Vector3 gradient = interpol.get1stDerivative(pos); - double dist = MathMan.sqrtApprox(last.distanceSq(gradient)); - last.mutX(gradient.getX()); - last.mutY(gradient.getY()); - last.mutZ(gradient.getZ()); - double change = dist * step; - // Accumulation is arbitrary, but much faster than calculation overlapping regions - if ((accumulation += change + step * 2) > blockDistance) { - accumulation -= blockDistance; + Vector3 lhs = getSidePos(interpol, pos, clipboard, false); + boolean doLeft = lhs == null || !lhs.round().equals(lastLHS); + if (doLeft && lhs != null) { + lastLHS.setComponents(lhs.round()); + } + + Vector3 rhs = getSidePos(interpol, pos, clipboard, true); + boolean doRight = rhs == null || !rhs.round().equals(lastRHS); + if (doRight && rhs != null) { + lastRHS.setComponents(rhs.round()); + } + + // Only paste if the edges have passed the previous edges + if (doLeft || doRight) { spline.pastePosition(pos); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/math/transform/RoundedTransform.java b/worldedit-core/src/main/java/com/sk89q/worldedit/math/transform/RoundedTransform.java index 0679f9ebe..8bdca82e8 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/math/transform/RoundedTransform.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/math/transform/RoundedTransform.java @@ -17,8 +17,7 @@ public class RoundedTransform implements Transform { @Override public Vector3 apply(Vector3 input) { Vector3 val = transform.apply(input); - return Vector3.at(Math.floor(val.getX() + 0.5), Math.floor(val.getY() + 0.5), Math - .floor(val.getY() + 0.5)); + return val.round(); } @Override From cd0dac813c880da5c996ec0ad387c6e0d6da4f3b Mon Sep 17 00:00:00 2001 From: Hazel Trinity Date: Sat, 15 Aug 2020 23:39:30 -0700 Subject: [PATCH 04/10] Incorrectly rounding results. --- .../math/interpolation/KochanekBartelsInterpolation.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/math/interpolation/KochanekBartelsInterpolation.java b/worldedit-core/src/main/java/com/sk89q/worldedit/math/interpolation/KochanekBartelsInterpolation.java index b4ae79cea..3024e8a2f 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/math/interpolation/KochanekBartelsInterpolation.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/math/interpolation/KochanekBartelsInterpolation.java @@ -22,6 +22,7 @@ package com.sk89q.worldedit.math.interpolation; import com.sk89q.worldedit.math.MutableBlockVector3; +import com.sk89q.worldedit.math.MutableVector3; import com.sk89q.worldedit.math.Vector3; import java.util.Collections; @@ -43,7 +44,7 @@ public class KochanekBartelsInterpolation implements Interpolation { private Vector3[] coeffC; private Vector3[] coeffD; private double scaling; - private final MutableBlockVector3 mutable = new MutableBlockVector3(); + private final MutableVector3 mutable = new MutableVector3(); public KochanekBartelsInterpolation() { setNodes(Collections.emptyList()); @@ -166,7 +167,7 @@ public class KochanekBartelsInterpolation implements Interpolation { mutable.mutX((a.getX() * r3 + b.getX() * r2 + c.getX() * remainder + d.getX())); mutable.mutY((a.getY() * r3 + b.getY() * r2 + c.getY() * remainder + d.getY())); mutable.mutZ((a.getZ() * r3 + b.getZ() * r2 + c.getZ() * remainder + d.getZ())); - return mutable.toVector3(); + return Vector3.at(mutable.getX(), mutable.getY(), mutable.getZ()); } @Override From e5f092c3efcecc6d8db135a815ad65169133a7d9 Mon Sep 17 00:00:00 2001 From: Hazel Trinity Date: Sun, 16 Aug 2020 01:08:35 -0700 Subject: [PATCH 05/10] Updated ClipboardSpline paste --- .../fawe/object/brush/sweep/ClipboardSpline.java | 3 ++- .../com/boydti/fawe/object/brush/sweep/Spline.java | 10 +++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/sweep/ClipboardSpline.java b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/sweep/ClipboardSpline.java index cfe5f99f9..849ba060e 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/sweep/ClipboardSpline.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/sweep/ClipboardSpline.java @@ -8,6 +8,7 @@ import com.sk89q.worldedit.function.operation.ForwardExtentCopy; import com.sk89q.worldedit.function.operation.Operation; import com.sk89q.worldedit.function.operation.Operations; import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.math.interpolation.Interpolation; import com.sk89q.worldedit.math.transform.AffineTransform; import com.sk89q.worldedit.math.transform.RoundedTransform; @@ -80,7 +81,7 @@ public class ClipboardSpline extends Spline { } @Override - protected int pasteBlocks(BlockVector3 target, BlockVector3 offset, double angle) throws MaxChangedBlocksException { + protected int pasteBlocks(BlockVector3 target, Vector3 offset, double angle) throws MaxChangedBlocksException { RoundedTransform transform = new RoundedTransform(new AffineTransform() .translate(offset) .rotateY(angle)); diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/sweep/Spline.java b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/sweep/Spline.java index d8aaf070b..c9ee1b8bb 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/sweep/Spline.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/sweep/Spline.java @@ -127,9 +127,9 @@ public abstract class Spline { Preconditions.checkArgument(position <= 1); // Calculate position from spline - BlockVector3 target = interpolation.getPosition(position).toBlockPoint(); - BlockVector3 offset = target.subtract(target.round()); - target = target.subtract(offset).round(); + Vector3 target = interpolation.getPosition(position); + BlockVector3 blockTarget = target.toBlockPoint(); + Vector3 offset = target.subtract(target.floor()); // Calculate rotation from spline @@ -139,10 +139,10 @@ public abstract class Spline { Math.atan2(direction.getZ(), direction.getX()) - Math.atan2(deriv2D.getZ(), deriv2D.getX()) ); - return pasteBlocks(target, offset, angle); + return pasteBlocks(blockTarget, offset, angle); } - protected abstract int pasteBlocks(BlockVector3 target, BlockVector3 offset, double angle) throws MaxChangedBlocksException; + protected abstract int pasteBlocks(BlockVector3 target, Vector3 offset, double angle) throws MaxChangedBlocksException; private void initSections() { int sectionCount = nodeCount - 1; From 5c32cc17a2fb6780a5f5295a7b5338a881b0bab5 Mon Sep 17 00:00:00 2001 From: Hazel Trinity Date: Sun, 16 Aug 2020 01:11:12 -0700 Subject: [PATCH 06/10] Used Reparameterized Interpolation --- .../fawe/object/brush/sweep/SweepBrush.java | 46 +++---------------- 1 file changed, 6 insertions(+), 40 deletions(-) diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/sweep/SweepBrush.java b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/sweep/SweepBrush.java index 250d2e956..27310d58b 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/sweep/SweepBrush.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/sweep/SweepBrush.java @@ -18,6 +18,7 @@ import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.math.interpolation.Interpolation; import com.sk89q.worldedit.math.interpolation.KochanekBartelsInterpolation; import com.sk89q.worldedit.math.interpolation.Node; +import com.sk89q.worldedit.math.interpolation.ReparametrisingInterpolation; import com.sk89q.worldedit.math.transform.AffineTransform; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.session.ClipboardHolder; @@ -41,22 +42,6 @@ public class SweepBrush implements Brush, ResettableTool { this.copies = copies > 0 ? copies : -1; } - private Vector3 getSidePos(Interpolation interpol, double position, Clipboard clipboard, boolean rightHand) { - Vector3 pos = interpol.getPosition(position); - Vector3 deriv = interpol.get1stDerivative(position); - double length = (rightHand ? 1 : -1) * Math.abs( - clipboard.getOrigin().getBlockZ() - clipboard.getRegion().getMinimumPoint().getBlockZ() - ); - - Vector3 cross = deriv.cross(Vector3.UNIT_Y); - if (cross.equals(Vector3.ZERO)) { - return null; - } - - Vector3 perpendicular = cross.normalize().multiply(length); - return pos.add(perpendicular); - } - @Override public void build(EditSession editSession, BlockVector3 position, Pattern pattern, double size) throws MaxChangedBlocksException { boolean visualization = editSession.getExtent() instanceof VisualExtent; @@ -82,7 +67,7 @@ public class SweepBrush implements Brush, ResettableTool { return; } - Interpolation interpol = new KochanekBartelsInterpolation(); + Interpolation interpol = new ReparametrisingInterpolation(new KochanekBartelsInterpolation()); List nodes = positions.stream().map(v -> { Node n = new Node(v.toVector3()); n.setTension(tension); @@ -114,29 +99,10 @@ public class SweepBrush implements Brush, ResettableTool { break; } case -1: { - double splineLength = interpol.arcLength(0D, 1D); - double blockDistance = 1d / splineLength; - double step = blockDistance / quality; - MutableVector3 lastLHS = new MutableVector3(getSidePos(interpol, 0, clipboard, false).round()); - MutableVector3 lastRHS = new MutableVector3(getSidePos(interpol, 0, clipboard, true).round()); - - for (double pos = 0D; pos <= 1D; pos += step) { - Vector3 lhs = getSidePos(interpol, pos, clipboard, false); - boolean doLeft = lhs == null || !lhs.round().equals(lastLHS); - if (doLeft && lhs != null) { - lastLHS.setComponents(lhs.round()); - } - - Vector3 rhs = getSidePos(interpol, pos, clipboard, true); - boolean doRight = rhs == null || !rhs.round().equals(lastRHS); - if (doRight && rhs != null) { - lastRHS.setComponents(rhs.round()); - } - - // Only paste if the edges have passed the previous edges - if (doLeft || doRight) { - spline.pastePosition(pos); - } + double length = interpol.arcLength(0, 1); + double step = 1 / (length * quality); + for (double pos = 0; pos <= 1; pos += step) { + spline.pastePosition(pos); } break; } From 054e60729b0a6117514cbf46d75ef93acfccd6d6 Mon Sep 17 00:00:00 2001 From: Hazel Trinity Date: Sun, 16 Aug 2020 02:15:05 -0700 Subject: [PATCH 07/10] Slightly better angle calculation --- .../com/boydti/fawe/object/brush/sweep/Spline.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/sweep/Spline.java b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/sweep/Spline.java index c9ee1b8bb..a1090bf09 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/sweep/Spline.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/sweep/Spline.java @@ -21,7 +21,7 @@ import java.util.List; */ public abstract class Spline { - private BlockVector2 direction = BlockVector2.at(1, 0); + private Vector2 direction = Vector2.at(1, 0); private final int nodeCount; protected EditSession editSession; @@ -77,10 +77,10 @@ public abstract class Spline { * is rotated by that angle to follow the curve slope. *

* The default direction is a (1;0) vector (pointing in the positive x-direction). - * @param direction A normalized vector representing the horizontal forward direction of the clipboard content + * @param direction A vector representing the horizontal forward direction of the clipboard content */ - public void setDirection(BlockVector2 direction) { - this.direction = direction; + public void setDirection(Vector2 direction) { + this.direction = direction.normalize(); } /** @@ -93,7 +93,7 @@ public abstract class Spline { * The default direction is a (1;0) vector (pointing in the positive x-direction). * @return A vector representing the horizontal forward direction of the clipboard content */ - public BlockVector2 getDirection() { + public Vector2 getDirection() { return direction; } @@ -136,9 +136,11 @@ public abstract class Spline { Vector3 deriv = interpolation.get1stDerivative(position); Vector2 deriv2D = Vector2.at(deriv.getX(), deriv.getZ()).normalize(); double angle = Math.toDegrees( - Math.atan2(direction.getZ(), direction.getX()) - Math.atan2(deriv2D.getZ(), deriv2D.getX()) + -Math.acos(direction.dot(deriv2D)) ); + angle = ((angle % 360) + 360) % 360; // Wrap to 360 degrees + return pasteBlocks(blockTarget, offset, angle); } From 5a482f4d38401974a25afc943016c6b98ae7a69f Mon Sep 17 00:00:00 2001 From: Hazel Trinity Date: Sun, 16 Aug 2020 15:40:53 -0700 Subject: [PATCH 08/10] Fixed argument exception If someone knows better please tell --- .../com/boydti/fawe/object/brush/sweep/Spline.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/sweep/Spline.java b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/sweep/Spline.java index a1090bf09..7c7e5cd92 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/sweep/Spline.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/sweep/Spline.java @@ -178,7 +178,15 @@ public abstract class Spline { double flexOffset = flexPosition - previousSection.flexStart; double uniOffset = flexOffset / previousSection.flexLength * previousSection.uniLength; - return previousSection.uniStart + uniOffset; + double finalPosition = previousSection.uniStart + uniOffset; + + //Really rough fix, but fixes a bug with no visual artifacts so it's probably ok? + //flexPosition very close to 1 causes outputs very slightly higher than 1 on rare occasions + if (finalPosition > 1) { + return 1; + } + + return finalPosition; } private class Section { From 73d70527f3a89231fe0f44c5f1aa93cfa7c817c5 Mon Sep 17 00:00:00 2001 From: Hazel Trinity Date: Sun, 16 Aug 2020 16:05:09 -0700 Subject: [PATCH 09/10] Signed angles --- .../com/boydti/fawe/object/brush/sweep/Spline.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/sweep/Spline.java b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/sweep/Spline.java index 7c7e5cd92..1f4da3cb7 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/sweep/Spline.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/sweep/Spline.java @@ -115,6 +115,13 @@ public abstract class Spline { } } + /** + * 2 dimensional "cross" product. cross2D(v1, v2) = |v1|*|v2|*sin(theta) or v1 X v2 taking Y to be 0 + */ + private double cross2D(Vector2 v1, Vector2 v2) { + return v1.getX() * v2.getZ() - v2.getX() * v1.getZ(); + } + /** * Paste structure at the provided position on the curve. The position will not be position-corrected * but will be passed directly to the interpolation algorithm. @@ -136,9 +143,9 @@ public abstract class Spline { Vector3 deriv = interpolation.get1stDerivative(position); Vector2 deriv2D = Vector2.at(deriv.getX(), deriv.getZ()).normalize(); double angle = Math.toDegrees( - -Math.acos(direction.dot(deriv2D)) + -Math.atan2(cross2D(direction, deriv2D), direction.dot(deriv2D)) ); - + angle = ((angle % 360) + 360) % 360; // Wrap to 360 degrees return pasteBlocks(blockTarget, offset, angle); From c725dd0b18eb27dafcf66bd20f16920e109b07d7 Mon Sep 17 00:00:00 2001 From: Hazel Trinity Date: Wed, 19 Aug 2020 10:13:41 -0700 Subject: [PATCH 10/10] Uses setDirection SweepBrush.java should be correct --- .../com/boydti/fawe/object/brush/sweep/SweepBrush.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/sweep/SweepBrush.java b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/sweep/SweepBrush.java index 27310d58b..429c7b9a9 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/sweep/SweepBrush.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/sweep/SweepBrush.java @@ -85,14 +85,16 @@ public class SweepBrush implements Brush, ResettableTool { Clipboard clipboard = holder.getClipboard(); BlockVector3 dimensions = clipboard.getDimensions(); - AffineTransform transform = new AffineTransform(); - if (dimensions.getBlockX() > dimensions.getBlockZ()) { - transform = transform.rotateY(90); - } double quality = Math.max(dimensions.getBlockX(), dimensions.getBlockZ()); + AffineTransform transform = new AffineTransform(); + ClipboardSpline spline = new ClipboardSpline(editSession, holder, interpol, transform, nodes.size()); + if (dimensions.getBlockX() > dimensions.getBlockZ()) { + spline.setDirection(Vector2.at(0, 1)); + } + switch (copies) { case 1: { spline.pastePosition(0D);