*More off axis rotation changes

Fix off axis rotation for certain angles
- Math error when calculating the inverse affine transform
Add -a flag to copyPaste brush (rotates based on view)
This commit is contained in:
Jesse Boyd 2017-08-24 22:11:03 +10:00
parent 70e1e00e23
commit d14b267cfd
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
12 changed files with 47 additions and 25 deletions

View File

@ -24,18 +24,20 @@ import com.sk89q.worldedit.function.visitor.RecursiveVisitor;
import com.sk89q.worldedit.math.transform.AffineTransform; import com.sk89q.worldedit.math.transform.AffineTransform;
import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.session.ClipboardHolder; import com.sk89q.worldedit.session.ClipboardHolder;
import com.sk89q.worldedit.util.Location;
public class CopyPastaBrush implements Brush, ResettableTool { public class CopyPastaBrush implements Brush, ResettableTool {
private final LocalSession session; private final LocalSession session;
private final boolean randomRotate;
private final Player player; private final Player player;
public boolean autoRotate, randomRotate;
public CopyPastaBrush(Player player, LocalSession session, boolean randomRotate) { public CopyPastaBrush(Player player, LocalSession session, boolean randomRotate, boolean autoRotate) {
session.setClipboard(null); session.setClipboard(null);
this.player = player; this.player = player;
this.session = session; this.session = session;
this.randomRotate = randomRotate; this.randomRotate = randomRotate;
this.autoRotate = autoRotate;
} }
@Override @Override
@ -65,7 +67,7 @@ public class CopyPastaBrush implements Brush, ResettableTool {
public boolean test(Vector vector) { public boolean test(Vector vector) {
if (super.test(vector) && vector.getBlockY() >= minY) { if (super.test(vector) && vector.getBlockY() >= minY) {
BaseBlock block = editSession.getLazyBlock(vector); BaseBlock block = editSession.getLazyBlock(vector);
if (block != EditSession.nullBlock) { if (block.getId() != 0) {
builder.add(vector, EditSession.nullBlock, block); builder.add(vector, EditSession.nullBlock, block);
return true; return true;
} }
@ -87,19 +89,33 @@ public class CopyPastaBrush implements Brush, ResettableTool {
BBC.COMMAND_COPY.send(fp, blocks); BBC.COMMAND_COPY.send(fp, blocks);
return; return;
} else { } else {
AffineTransform transform = null;
if (randomRotate) { if (randomRotate) {
if (transform == null) transform = new AffineTransform();
int rotate = 90 * PseudoRandom.random.nextInt(4); int rotate = 90 * PseudoRandom.random.nextInt(4);
clipboard.setTransform(rotate != 0 ? new AffineTransform().rotateY(rotate) : new AffineTransform()); transform = transform.rotateY(rotate);
}
if (autoRotate) {
if (transform == null) transform = new AffineTransform();
Location loc = editSession.getPlayer().getPlayer().getLocation();
float yaw = loc.getYaw();
float pitch = loc.getPitch();
transform = transform.rotateY((-yaw) % 360);
transform = transform.rotateX(pitch - 90);
}
if (transform != null && !transform.isIdentity()) {
clipboard.setTransform(transform);
} }
Clipboard faweClip = clipboard.getClipboard(); Clipboard faweClip = clipboard.getClipboard();
Region region = faweClip.getRegion(); Region region = faweClip.getRegion();
Vector centerOffset = region.getCenter().subtract(faweClip.getOrigin());
Operation operation = clipboard Operation operation = clipboard
.createPaste(editSession, editSession.getWorld().getWorldData()) .createPaste(editSession, editSession.getWorldData())
.to(position.add(0, 1, 0)) .to(position.add(0, 1, 0))
.ignoreAirBlocks(true) .ignoreAirBlocks(true)
.build(); .build();
Operations.completeLegacy(operation); Operations.completeLegacy(operation);
editSession.flushQueue();
} }
} }
} }

View File

@ -29,7 +29,7 @@ public class PopulateSchem implements Brush {
public void build(EditSession editSession, Vector position, Pattern pattern, double size) throws MaxChangedBlocksException { public void build(EditSession editSession, Vector position, Pattern pattern, double size) throws MaxChangedBlocksException {
new MaskTraverser(mask).reset(editSession); new MaskTraverser(mask).reset(editSession);
SchemGen gen = new SchemGen(mask, editSession, editSession.getWorldData(), clipboards, randomRotate); SchemGen gen = new SchemGen(mask, editSession, editSession.getWorldData(), clipboards, randomRotate);
CuboidRegion cuboid = new CuboidRegion(position.subtract(size, size, size), position.add(size, size, size)); CuboidRegion cuboid = new CuboidRegion(editSession.getWorld(), position.subtract(size, size, size), position.add(size, size, size));
try { try {
editSession.addSchems(cuboid, mask, editSession.getWorldData(), clipboards, rarity, randomRotate); editSession.addSchems(cuboid, mask, editSession.getWorldData(), clipboards, rarity, randomRotate);
} catch (WorldEditException e) { } catch (WorldEditException e) {

View File

@ -7,6 +7,7 @@ import com.sk89q.worldedit.command.tool.brush.Brush;
import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.function.pattern.Pattern;
public class SpikeBrush implements Brush { public class SpikeBrush implements Brush {
@Override @Override
public void build(EditSession editSession, Vector position, Pattern pattern, double size) throws MaxChangedBlocksException { public void build(EditSession editSession, Vector position, Pattern pattern, double size) throws MaxChangedBlocksException {

View File

@ -47,7 +47,7 @@ public class StencilBrush extends HeightBrush {
int cutoff = onlyWhite ? maxY : 0; int cutoff = onlyWhite ? maxY : 0;
final SolidBlockMask solid = new SolidBlockMask(editSession); final SolidBlockMask solid = new SolidBlockMask(editSession);
final AdjacentAnyMask adjacent = new AdjacentAnyMask(Masks.negate(solid)); final AdjacentAnyMask adjacent = new AdjacentAnyMask(Masks.negate(solid));
RegionMask region = new RegionMask(new CuboidRegion(position.subtract(size, size, size), position.add(size, size, size))); RegionMask region = new RegionMask(new CuboidRegion(editSession.getWorld(), position.subtract(size, size, size), position.add(size, size, size)));
RecursiveVisitor visitor = new RecursiveVisitor(new Mask() { RecursiveVisitor visitor = new RecursiveVisitor(new Mask() {
@Override @Override
public boolean test(Vector vector) { public boolean test(Vector vector) {

View File

@ -3,7 +3,6 @@ package com.boydti.fawe.object.brush.heightmap;
import com.boydti.fawe.object.IntegerPair; import com.boydti.fawe.object.IntegerPair;
import com.boydti.fawe.util.MainUtil; import com.boydti.fawe.util.MainUtil;
import com.boydti.fawe.util.MathMan; import com.boydti.fawe.util.MathMan;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.extent.clipboard.Clipboard;
@ -79,7 +78,7 @@ public class ScalableHeightMap implements com.boydti.fawe.object.brush.heightmap
for (int y = minY; y <= maxY; y++) { for (int y = minY; y <= maxY; y++) {
pos.mutY(y); pos.mutY(y);
BaseBlock block = clipboard.getBlock(pos); BaseBlock block = clipboard.getBlock(pos);
if (block != EditSession.nullBlock) { if (block.getId() != 0) {
highestY = y + 1; highestY = y + 1;
} }
} }

View File

@ -114,7 +114,7 @@ public class PNGWriter implements ClipboardWriter {
mutableTop.mutY(y + 1); mutableTop.mutY(y + 1);
mutableRight.mutY(y); mutableRight.mutY(y);
mutableLeft.mutY(y); mutableLeft.mutY(y);
if (clipboard.getBlock(mutableTop) != EditSession.nullBlock && clipboard.getBlock(mutableRight) != EditSession.nullBlock && clipboard.getBlock(mutableLeft) != EditSession.nullBlock) { if (clipboard.getBlock(mutableTop).getId() != 0 && clipboard.getBlock(mutableRight) != EditSession.nullBlock && clipboard.getBlock(mutableLeft).getId() != 0 ) {
continue; continue;
} }
double cpy = cpy2 - dpxi[y - y0]; double cpy = cpy2 - dpxi[y - y0];

View File

@ -1430,13 +1430,13 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
int freeSpot = startCheckY; int freeSpot = startCheckY;
for (int y = startCheckY; y <= endY; y++) { for (int y = startCheckY; y <= endY; y++) {
if (y < startPerformY) { if (y < startPerformY) {
if (getLazyBlock(x, y, z) != EditSession.nullBlock) { if (getLazyBlock(x, y, z).getId() != 0) {
freeSpot = y + 1; freeSpot = y + 1;
} }
continue; continue;
} }
BaseBlock block = getLazyBlock(x, y, z); BaseBlock block = getLazyBlock(x, y, z);
if (block != EditSession.nullBlock) { if (block.getId() != 0) {
if (freeSpot != y) { if (freeSpot != y) {
setBlock(x, freeSpot, z, block); setBlock(x, freeSpot, z, block);
setBlock(x, y, z, replace); setBlock(x, y, z, replace);
@ -2217,11 +2217,11 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
return makeCylinder(pos, block, radiusX, radiusZ, height, 0, filled); return makeCylinder(pos, block, radiusX, radiusZ, height, 0, filled);
} }
public int makeHollowCylinder(Vector pos, final Pattern block, double radiusX, double radiusZ, int height, int thickness) { public int makeHollowCylinder(Vector pos, final Pattern block, double radiusX, double radiusZ, int height, double thickness) {
return makeCylinder(pos, block, radiusX, radiusZ, height, thickness, false); return makeCylinder(pos, block, radiusX, radiusZ, height, thickness, false);
} }
private int makeCylinder(Vector pos, final Pattern block, double radiusX, double radiusZ, int height, int thickness, final boolean filled) { private int makeCylinder(Vector pos, final Pattern block, double radiusX, double radiusZ, int height, double thickness, final boolean filled) {
radiusX += 0.5; radiusX += 0.5;
radiusZ += 0.5; radiusZ += 0.5;

View File

@ -783,17 +783,19 @@ public class BrushCommands extends MethodCommands {
help = "Left click the base of an object to copy.\n" + help = "Left click the base of an object to copy.\n" +
"Right click to paste\n" + "Right click to paste\n" +
"The -r flag Will apply random rotation on paste\n" + "The -r flag Will apply random rotation on paste\n" +
"The -a flag Will apply auto view based rotation on paste\n" +
"Note: Works well with the clipboard scroll action\n" + "Note: Works well with the clipboard scroll action\n" +
"Video: https://www.youtube.com/watch?v=RPZIaTbqoZw", "Video: https://www.youtube.com/watch?v=RPZIaTbqoZw",
min = 0, min = 0,
max = 1 max = 1
) )
@CommandPermissions("worldedit.brush.copy") @CommandPermissions("worldedit.brush.copy")
public BrushSettings copy(Player player, LocalSession session, @Optional("5") double radius, @Switch('r') boolean rotate, CommandContext context) throws WorldEditException { public BrushSettings copy(Player player, LocalSession session, @Optional("5") double radius, @Switch('r') boolean randomRotate, @Switch('a') boolean autoRotate, CommandContext context) throws WorldEditException {
worldEdit.checkMaxBrushRadius(radius); worldEdit.checkMaxBrushRadius(radius);
player.print(BBC.getPrefix() + BBC.BRUSH_COPY.f(radius)); player.print(BBC.getPrefix() + BBC.BRUSH_COPY.f(radius));
return get(context) return get(context)
.setBrush(new CopyPastaBrush(player, session, rotate)) .setBrush(new CopyPastaBrush(player, session, randomRotate, autoRotate))
.setSize(radius); .setSize(radius);
} }

View File

@ -184,7 +184,7 @@ public class GenerationCommands extends MethodCommands {
) )
@CommandPermissions("worldedit.generation.cylinder") @CommandPermissions("worldedit.generation.cylinder")
@Logging(PLACEMENT) @Logging(PLACEMENT)
public void hcyl(FawePlayer fp, Player player, LocalSession session, EditSession editSession, Pattern pattern, Vector2D radius, @Optional("1") int height, @Range(min = 1) @Optional("1") int thickness, CommandContext context) throws WorldEditException, ParameterException { public void hcyl(FawePlayer fp, Player player, LocalSession session, EditSession editSession, Pattern pattern, Vector2D radius, @Optional("1") int height, @Range(min = 1) @Optional("1") double thickness, CommandContext context) throws WorldEditException, ParameterException {
double max = MathMan.max(radius.getBlockX(), radius.getBlockZ()); double max = MathMan.max(radius.getBlockX(), radius.getBlockZ());
worldEdit.checkMaxRadius(max); worldEdit.checkMaxRadius(max);
fp.checkConfirmationRadius(getArguments(context), (int) max); fp.checkConfirmationRadius(getArguments(context), (int) max);

View File

@ -25,6 +25,7 @@ import com.boydti.fawe.object.extent.BlockTranslateExtent;
import com.boydti.fawe.object.extent.PositionTransformExtent; import com.boydti.fawe.object.extent.PositionTransformExtent;
import com.boydti.fawe.object.function.block.BiomeCopy; import com.boydti.fawe.object.function.block.BiomeCopy;
import com.boydti.fawe.object.function.block.SimpleBlockCopy; import com.boydti.fawe.object.function.block.SimpleBlockCopy;
import com.boydti.fawe.util.MaskTraverser;
import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.WorldEditException;
@ -249,8 +250,10 @@ public class ForwardExtentCopy implements Operation {
} else { } else {
queue = null; queue = null;
} }
Extent finalDest = destination; Extent finalDest = destination;
Vector translation = to.subtract(from); Vector translation = to.subtract(from);
if (!translation.equals(Vector.ZERO)) { if (!translation.equals(Vector.ZERO)) {
finalDest = new BlockTranslateExtent(finalDest, translation.getBlockX(), translation.getBlockY(), translation.getBlockZ()); finalDest = new BlockTranslateExtent(finalDest, translation.getBlockX(), translation.getBlockY(), translation.getBlockZ());
} }
@ -264,6 +267,7 @@ public class ForwardExtentCopy implements Operation {
RegionFunction copy = new SimpleBlockCopy(transExt, finalDest); RegionFunction copy = new SimpleBlockCopy(transExt, finalDest);
if (sourceMask != Masks.alwaysTrue()) { if (sourceMask != Masks.alwaysTrue()) {
new MaskTraverser(sourceMask).reset(transExt);
copy = new RegionMaskingFilter(sourceMask, copy); copy = new RegionMaskingFilter(sourceMask, copy);
} }
if (sourceFunction != null) { if (sourceFunction != null) {

View File

@ -150,7 +150,7 @@ public class AffineTransform implements Transform, Serializable {
* *
* @return the determinant of the transform. * @return the determinant of the transform.
*/ */
private double determinant() { public double determinant() {
return m00 * (m11 * m22 - m12 * m21) - m01 * (m10 * m22 - m20 * m12) return m00 * (m11 * m22 - m12 * m21) - m01 * (m10 * m22 - m20 * m12)
+ m02 * (m10 * m21 - m20 * m11); + m02 * (m10 * m21 - m20 * m11);
} }
@ -163,17 +163,17 @@ public class AffineTransform implements Transform, Serializable {
double det = this.determinant(); double det = this.determinant();
return new AffineTransform( return new AffineTransform(
(m11 * m22 - m21 * m12) / det, (m11 * m22 - m21 * m12) / det,
(m21 * m01 - m01 * m22) / det, (m02 * m21 - m22 * m01) / det,
(m01 * m12 - m11 * m02) / det, (m01 * m12 - m11 * m02) / det,
(m01 * (m22 * m13 - m12 * m23) + m02 * (m11 * m23 - m21 * m13) (m01 * (m22 * m13 - m12 * m23) + m02 * (m11 * m23 - m21 * m13)
- m03 * (m11 * m22 - m21 * m12)) / det, - m03 * (m11 * m22 - m21 * m12)) / det,
(m20 * m12 - m10 * m22) / det, (m12 * m20 - m22 * m10) / det,
(m00 * m22 - m20 * m02) / det, (m00 * m22 - m20 * m02) / det,
(m10 * m02 - m00 * m12) / det, (m02 * m10 - m12 * m00) / det,
(m00 * (m12 * m23 - m22 * m13) - m02 * (m10 * m23 - m20 * m13) (m00 * (m12 * m23 - m22 * m13) - m02 * (m10 * m23 - m20 * m13)
+ m03 * (m10 * m22 - m20 * m12)) / det, + m03 * (m10 * m22 - m20 * m12)) / det,
(m10 * m21 - m20 * m11) / det, (m10 * m21 - m20 * m11) / det,
(m20 * m01 - m00 * m21) / det, (m01 * m20 - m21 * m00) / det,
(m00 * m11 - m10 * m01) / det, (m00 * m11 - m10 * m01) / det,
(m00 * (m21 * m13 - m11 * m23) + m01 * (m10 * m23 - m20 * m13) (m00 * (m21 * m13 - m11 * m23) + m01 * (m10 * m23 - m20 * m13)
- m03 * (m10 * m21 - m20 * m11)) / det); - m03 * (m10 * m21 - m20 * m11)) / det);

View File

@ -137,8 +137,8 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion {
if (pos1 == null || pos2 == null) { if (pos1 == null || pos2 == null) {
return; return;
} }
pos1 = pos1.clampY(0, world == null ? 255 : world.getMaxY()); pos1 = pos1.clampY(world == null ? Integer.MIN_VALUE : 0, world == null ? Integer.MAX_VALUE : world.getMaxY());
pos2 = pos2.clampY(0, world == null ? 255 : world.getMaxY()); pos2 = pos2.clampY(world == null ? Integer.MIN_VALUE : 0, world == null ? Integer.MAX_VALUE : world.getMaxY());
Vector min = getMinimumPoint(); Vector min = getMinimumPoint();
Vector max = getMaximumPoint(); Vector max = getMaximumPoint();
minX = min.getBlockX(); minX = min.getBlockX();