diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/RainboomAbilitySpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/RainboomAbilitySpell.java index d3643ab8..4e2755d4 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/RainboomAbilitySpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/RainboomAbilitySpell.java @@ -66,7 +66,7 @@ public class RainboomAbilitySpell extends AbstractSpell { source.findAllEntitiesInRange(RADIUS).forEach(e -> { e.damage(MagicalDamageSource.create("rainboom", source).setBreakSunglasses(), 6); }); - EFFECT_RANGE.offset(source.getOrigin()).getBlockPositions().forEach(pos -> { + EFFECT_RANGE.translate(source.getOrigin()).getBlockPositions().forEach(pos -> { BlockState state = source.getReferenceWorld().getBlockState(pos); if (state.isIn(UTags.FRAGILE) && canBreak(pos, owner)) { owner.world.breakBlock(pos, true); diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DarkVortexSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DarkVortexSpell.java index e11ca88d..93c6a2ca 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DarkVortexSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DarkVortexSpell.java @@ -155,7 +155,7 @@ public class DarkVortexSpell extends AttractiveSpell implements ProjectileSpell if (radius > 2) { Vec3d origin = getOrigin(source); - new Sphere(false, radius).offset(origin).getBlockPositions().forEach(i -> { + new Sphere(false, radius).translate(origin).getBlockPositions().forEach(i -> { if (!canAffect(source, i)) { return; } diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/FireSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/FireSpell.java index 9fcb24ed..a9ba00e9 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/FireSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/FireSpell.java @@ -66,7 +66,7 @@ public class FireSpell extends AbstractAreaEffectSpell implements ProjectileSpel generateParticles(source); } - return new Sphere(false, Math.max(0, 4 + getTraits().get(Trait.POWER))).offset(source.getOrigin()).getBlockPositions().reduce(false, + return new Sphere(false, Math.max(0, 4 + getTraits().get(Trait.POWER))).translate(source.getOrigin()).getBlockPositions().reduce(false, (r, i) -> source.canModifyAt(i) && applyBlocks(source.getReferenceWorld(), i), (a, b) -> a || b) || applyEntities(null, source.getReferenceWorld(), source.getOriginVector()); diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/HydrophobicSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/HydrophobicSpell.java index a87adb23..8d7bb288 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/HydrophobicSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/HydrophobicSpell.java @@ -51,7 +51,7 @@ public class HydrophobicSpell extends AbstractSpell { if (!source.isClient()) { World world = source.getReferenceWorld(); - Shape area = new Sphere(false, getRange(source)).offset(source.getOriginVector()); + Shape area = new Sphere(false, getRange(source)).translate(source.getOriginVector()); storedFluidPositions.removeIf(entry -> { if (!area.isPointInside(Vec3d.ofCenter(entry.pos()))) { diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/IceSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/IceSpell.java index 0ad75241..4e013f85 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/IceSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/IceSpell.java @@ -42,7 +42,7 @@ public class IceSpell extends AbstractSpell { public boolean tick(Caster source, Situation situation) { boolean submerged = source.getEntity().isSubmergedInWater() || source.getEntity().isSubmergedIn(FluidTags.LAVA); - long blocksAffected = OUTER_RANGE.offset(source.getOrigin()).getBlockPositions().filter(i -> { + long blocksAffected = OUTER_RANGE.translate(source.getOrigin()).getBlockPositions().filter(i -> { if (source.canModifyAt(i) && applyBlockSingle(source.getEntity(), source.getReferenceWorld(), i, situation)) { if (submerged & source.getOrigin().isWithinDistance(i, RADIUS - 1)) { diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/PortalSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/PortalSpell.java index 90350a6d..68608771 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/PortalSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/PortalSpell.java @@ -43,7 +43,7 @@ public class PortalSpell extends AbstractSpell implements PlaceableSpell.Placeme private float pitch; private float yaw; - private PointGenerator particleArea = PARTICLE_AREA; + private Shape particleArea = PARTICLE_AREA; protected PortalSpell(CustomisedSpellType type) { super(type); diff --git a/src/main/java/com/minelittlepony/unicopia/client/particle/CloudsEscapingParticle.java b/src/main/java/com/minelittlepony/unicopia/client/particle/CloudsEscapingParticle.java index e6a048b0..50792cfe 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/particle/CloudsEscapingParticle.java +++ b/src/main/java/com/minelittlepony/unicopia/client/particle/CloudsEscapingParticle.java @@ -31,7 +31,7 @@ public class CloudsEscapingParticle extends GroundPoundParticle { double columnHeight = 1 + age / 30; new Sphere(true, columnHeight, 1, 1, 1) - .offset(center) + .translate(center) .randomPoints(random) .forEach(point -> { ParticleUtils.spawnParticle(world, ParticleTypes.CLOUD, point, vel); diff --git a/src/main/java/com/minelittlepony/unicopia/client/particle/GroundPoundParticle.java b/src/main/java/com/minelittlepony/unicopia/client/particle/GroundPoundParticle.java index 93e67333..0e9c2e10 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/particle/GroundPoundParticle.java +++ b/src/main/java/com/minelittlepony/unicopia/client/particle/GroundPoundParticle.java @@ -45,7 +45,7 @@ public class GroundPoundParticle extends Particle { protected void spawnChildParticles() { Vec3d vel = new Vec3d(0, (0.5 + (Math.sin(age) * 2.5)) * 5, 0); - new Sphere(true, age, 1, 0, 1).offset(getPos()).randomPoints(random).forEach(point -> { + new Sphere(true, age, 1, 0, 1).translate(getPos()).randomPoints(random).forEach(point -> { BlockPos pos = new BlockPos(point).down(); BlockState state = world.getBlockState(pos); diff --git a/src/main/java/com/minelittlepony/unicopia/particle/ParticleSource.java b/src/main/java/com/minelittlepony/unicopia/particle/ParticleSource.java index f7e9f88b..19c4ad51 100644 --- a/src/main/java/com/minelittlepony/unicopia/particle/ParticleSource.java +++ b/src/main/java/com/minelittlepony/unicopia/particle/ParticleSource.java @@ -34,7 +34,7 @@ public interface ParticleSource extends ParticleSpawner { } default void spawnParticles(Vec3d pos, PointGenerator area, int count, Consumer particleSpawner) { - area.offset(pos).randomPoints(count, getReferenceWorld().random).forEach(particleSpawner); + area.translate(pos).randomPoints(count, getReferenceWorld().random).forEach(particleSpawner); } @Override diff --git a/src/main/java/com/minelittlepony/unicopia/particle/ParticleUtils.java b/src/main/java/com/minelittlepony/unicopia/particle/ParticleUtils.java index 0f77a9c3..f851f53e 100644 --- a/src/main/java/com/minelittlepony/unicopia/particle/ParticleUtils.java +++ b/src/main/java/com/minelittlepony/unicopia/particle/ParticleUtils.java @@ -16,7 +16,7 @@ public interface ParticleUtils { static PointGenerator getShapeFor(Entity entity) { final double halfDist = Math.abs(entity.getStandingEyeHeight() / 1.5); final double middle = entity.getBoundingBox().minY + halfDist; - return new Sphere(false, Math.abs((float)halfDist + entity.getWidth())).offset(new Vec3d(entity.getX(), middle, entity.getZ())); + return new Sphere(false, Math.abs((float)halfDist + entity.getWidth())).translate(new Vec3d(entity.getX(), middle, entity.getZ())); } static void spawnParticles(ParticleEffect effect, Entity entity, int count) { @@ -24,7 +24,7 @@ public interface ParticleUtils { } static void spawnParticles(ParticleEffect effect, World world, Vec3d origin, int count) { - spawnParticles(world, Sphere.UNIT_SPHERE.offset(origin), effect, count); + spawnParticles(world, Sphere.UNIT_SPHERE.translate(origin), effect, count); } static void spawnParticles(World world, PointGenerator points, ParticleEffect effect, int count) { diff --git a/src/main/java/com/minelittlepony/unicopia/util/VecHelper.java b/src/main/java/com/minelittlepony/unicopia/util/VecHelper.java index cb5b5daf..f6c3e4a2 100644 --- a/src/main/java/com/minelittlepony/unicopia/util/VecHelper.java +++ b/src/main/java/com/minelittlepony/unicopia/util/VecHelper.java @@ -12,6 +12,10 @@ import net.minecraft.world.EntityView; public interface VecHelper { + static Vec3d divide(Vec3d one, Vec3d two) { + return new Vec3d(one.x / two.x, one.y / two.y, one.z / two.z); + } + static Vec3d supply(DoubleSupplier rng) { return new Vec3d(rng.getAsDouble(), rng.getAsDouble(), rng.getAsDouble()); } diff --git a/src/main/java/com/minelittlepony/unicopia/util/shape/Cylinder.java b/src/main/java/com/minelittlepony/unicopia/util/shape/Cylinder.java index 7caf4195..f360ba19 100644 --- a/src/main/java/com/minelittlepony/unicopia/util/shape/Cylinder.java +++ b/src/main/java/com/minelittlepony/unicopia/util/shape/Cylinder.java @@ -49,20 +49,21 @@ public class Cylinder implements Shape { } @Override - public double getVolumeOfSpawnableSpace() { + public double getVolume() { return volume; } private double computeSpawnableSpace() { - if (hollow) { - if (stretchX != stretchZ) { - double result = 3 * (stretchX + stretchZ); - result -= Math.sqrt((10 * stretchX * stretchZ) + 3 * ((stretchX * stretchX) + (stretchZ * stretchZ))); - return Math.PI * result; - } - return 2 * Math.PI * rad * stretchX * height; + if (!hollow) { + return Math.PI * (stretchX * rad * stretchZ * rad) * height; } - return Math.PI * (stretchX * rad * stretchZ * rad) * height; + + if (stretchX != stretchZ) { + double result = 3 * (stretchX + stretchZ); + result -= Math.sqrt((10 * stretchX * stretchZ) + 3 * ((stretchX * stretchX) + (stretchZ * stretchZ))); + return Math.PI * result; + } + return 2 * Math.PI * rad * stretchX * height; } @Override diff --git a/src/main/java/com/minelittlepony/unicopia/util/shape/Line.java b/src/main/java/com/minelittlepony/unicopia/util/shape/Line.java index f345ea23..282f79f2 100644 --- a/src/main/java/com/minelittlepony/unicopia/util/shape/Line.java +++ b/src/main/java/com/minelittlepony/unicopia/util/shape/Line.java @@ -1,84 +1,54 @@ package com.minelittlepony.unicopia.util.shape; +import com.minelittlepony.unicopia.util.VecHelper; + import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.random.Random; /** * A lonely Line. The simplest form of shape. - * */ public class Line implements Shape { - private final double len; + private final double length; - private final double dX; - private final double dY; - private final double dZ; - - private final double sX; - private final double sY; - private final double sZ; - - /** - * Creates a line with a given length, starting point, and gradient represented - * by another point. - * - * @param length Length of this line - * @param startX Offset X from origin - * @param startY Offset Y from origin - * @param startZ Offset Z from origin - * @param deltaX Change in X - * @param deltaY Change in Y - * @param deltaZ Change in Z - */ - public Line(double length, double startX, double startY, double startZ, double deltaX, double deltaY, double deltaZ) { - len = length; - dX = deltaX; - dY = deltaY; - dZ = deltaZ; - sX = startX; - sY = startY; - sZ = startZ; - } + private final Vec3d gradient; public Line(Vec3d start, Vec3d end) { Vec3d lenV = end.subtract(start); + length = lenV.length(); + this.gradient = lenV.multiply(1/length); + } - len = lenV.length(); - - sX = start.x; - sY = start.y; - sZ = start.z; - - dX = lenV.x / len; - dY = lenV.y / len; - dZ = lenV.z / len; + public Line(double length, Vec3d gradient) { + this.length = length; + this.gradient = gradient.normalize(); } @Override - public double getVolumeOfSpawnableSpace() { - return len; + public double getVolume() { + return length; } @Override public Vec3d computePoint(Random rand) { - double distance = MathHelper.nextDouble(rand, 0, len); - return new Vec3d(dX, dY, dZ).multiply(distance).add(sX, sY, sZ); + return gradient.multiply(MathHelper.nextDouble(rand, 0, length)); } @Override public boolean isPointInside(Vec3d point) { - return point.x/dX == point.y/dY && point.x/dX == point.z/dZ; + Vec3d divided = VecHelper.divide(point, gradient); + return divided.x == divided.y && divided.x == divided.z; } @Override public Vec3d getLowerBound() { - return new Vec3d(sX, sY, sZ); + return Vec3d.ZERO; } @Override public Vec3d getUpperBound() { - return new Vec3d(sX + dX, sY + dY, sZ + dZ).multiply(len); + return gradient.multiply(length); } } diff --git a/src/main/java/com/minelittlepony/unicopia/util/shape/PointGenerator.java b/src/main/java/com/minelittlepony/unicopia/util/shape/PointGenerator.java index 00c0c155..10a0bd90 100644 --- a/src/main/java/com/minelittlepony/unicopia/util/shape/PointGenerator.java +++ b/src/main/java/com/minelittlepony/unicopia/util/shape/PointGenerator.java @@ -2,7 +2,6 @@ package com.minelittlepony.unicopia.util.shape; import java.util.Spliterator; import java.util.Spliterators.AbstractSpliterator; -import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; import java.util.stream.Stream; import java.util.stream.StreamSupport; @@ -15,35 +14,21 @@ import net.minecraft.util.math.random.Random; *Interface for a 3d shape, used for spawning particles in a designated area (or anything else you need shapes for). */ public interface PointGenerator { - /** - * Get the volume of space filled by this shape, or the surface area if hollow. - * - * @return double volume - */ - double getVolumeOfSpawnableSpace(); - /** * Computes a random coordinate that falls within this shape's designated area. */ Vec3d computePoint(Random rand); - /** - * Returns a sequence of random points dealed out to uniformly fill this shape's area. - */ - default Stream randomPoints(Random rand) { - return randomPoints((int)getVolumeOfSpawnableSpace(), rand); - } - /** * Returns a sequence of N random points. */ default Stream randomPoints(int n, Random rand) { - AtomicInteger atom = new AtomicInteger(n); return StreamSupport.stream(new AbstractSpliterator(n, Spliterator.SIZED) { + private int index = n; + @Override public boolean tryAdvance(Consumer consumer) { - - if (atom.decrementAndGet() >= 0) { + if (--index >= 0) { consumer.accept(computePoint(rand)); return true; } @@ -54,37 +39,17 @@ public interface PointGenerator { } /** - * Returns a stream of block positions. + * Returns a new shape with after applying additional rotation. */ - Stream getBlockPositions(); - - /** - * Returns a new point generator where all of its points are offset by the specified amount. - */ - default PointGenerator offset(Vec3i offset) { - return offset(Vec3d.of(offset)); + default PointGenerator rotate(float pitch, float yaw) { + return pitch == 0 && yaw == 0 ? this : new RotatedPointGenerator(this, pitch, yaw); } - /** - * Returns a new point generator where all of its points are offset by the specified amount. - */ - default PointGenerator offset(Vec3d offset) { - final PointGenerator source = this; - return new PointGenerator() { - @Override - public double getVolumeOfSpawnableSpace() { - return source.getVolumeOfSpawnableSpace(); - } + default PointGenerator translate(Vec3i offset) { + return offset.equals(Vec3i.ZERO) ? this : translate(Vec3d.of(offset)); + } - @Override - public Vec3d computePoint(Random rand) { - return source.computePoint(rand).add(offset); - } - - @Override - public Stream getBlockPositions() { - return source.getBlockPositions().map(pos -> pos.add(offset.x, offset.y, offset.z)); - } - }; + default PointGenerator translate(Vec3d offset) { + return offset.equals(Vec3d.ZERO) ? this : new TranslatedPointGenerator(this, offset); } } diff --git a/src/main/java/com/minelittlepony/unicopia/util/shape/RotatedPointGenerator.java b/src/main/java/com/minelittlepony/unicopia/util/shape/RotatedPointGenerator.java new file mode 100644 index 00000000..e5b315d2 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/util/shape/RotatedPointGenerator.java @@ -0,0 +1,48 @@ +package com.minelittlepony.unicopia.util.shape; + +import net.minecraft.util.math.*; +import net.minecraft.util.math.random.Random; + +record RotatedPointGenerator ( + PointGenerator original, + float pitch, + float yaw + ) implements Shape { + @Override + public double getVolume() { + return ((Shape)original).getVolume(); + } + + @Override + public Vec3d computePoint(Random rand) { + return rotate(original.computePoint(rand)); + } + + @Override + public Vec3d getLowerBound() { + return rotate(((Shape)original).getLowerBound()); + } + + @Override + public Vec3d getUpperBound() { + return rotate(((Shape)original).getUpperBound()); + } + + @Override + public boolean isPointInside(Vec3d point) { + return ((Shape)original).isPointInside(point.rotateY(-yaw).rotateX(-pitch)); + } + + private Vec3d rotate(Vec3d vec) { + return vec.rotateX(pitch).rotateY(yaw); + } + + @Override + public Shape rotate(float pitch, float yaw) { + if (pitch == 0 && yaw == 0) { + return this; + } + + return new RotatedPointGenerator(this, this.pitch + pitch, this.yaw + yaw); + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/util/shape/RotatedShape.java b/src/main/java/com/minelittlepony/unicopia/util/shape/RotatedShape.java deleted file mode 100644 index 4f17db2b..00000000 --- a/src/main/java/com/minelittlepony/unicopia/util/shape/RotatedShape.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.minelittlepony.unicopia.util.shape; - -import net.minecraft.util.math.*; -import net.minecraft.util.math.random.Random; - -final class RotatedShape implements Shape { - private final float pitch; - private final float yaw; - - private final Shape original; - - RotatedShape(Shape original, float pitch, float yaw) { - this.original = original; - this.pitch = pitch; - this.yaw = yaw; - } - - @Override - public double getVolumeOfSpawnableSpace() { - return original.getVolumeOfSpawnableSpace(); - } - - @Override - public Vec3d computePoint(Random rand) { - return original.computePoint(rand).rotateX(pitch).rotateY(yaw); - } - - @Override - public Vec3d getLowerBound() { - return original.getLowerBound().rotateX(pitch).rotateY(yaw); - } - - @Override - public Vec3d getUpperBound() { - return original.getUpperBound().rotateX(pitch).rotateY(yaw); - } - - @Override - public boolean isPointInside(Vec3d point) { - return original.isPointInside(point.rotateY(-yaw).rotateX(-pitch)); - } - - @Override - public Shape rotate(float pitch, float yaw) { - if (pitch == 0 && yaw == 0) { - return this; - } - - return new RotatedShape(this, this.pitch + pitch, this.yaw + yaw); - } -} diff --git a/src/main/java/com/minelittlepony/unicopia/util/shape/Shape.java b/src/main/java/com/minelittlepony/unicopia/util/shape/Shape.java index b7cea532..8ac9f38e 100644 --- a/src/main/java/com/minelittlepony/unicopia/util/shape/Shape.java +++ b/src/main/java/com/minelittlepony/unicopia/util/shape/Shape.java @@ -10,6 +10,13 @@ import net.minecraft.util.math.random.Random; *Interface for a 3d shape, used for spawning particles in a designated area (or anything else you need shapes for). */ public interface Shape extends PointGenerator { + /** + * Get the volume of space filled by this shape, or the surface area if hollow. + * + * @return double volume + */ + double getVolume(); + /** * Gets the lower bounds of the region occupied by this shape. */ @@ -28,7 +35,6 @@ public interface Shape extends PointGenerator { /** * Returns a stream of all block positions that fit inside this shape. */ - @Override default Stream getBlockPositions() { return BlockPos.stream( new BlockPos(getLowerBound()), @@ -36,60 +42,28 @@ public interface Shape extends PointGenerator { ).filter(pos -> isPointInside(Vec3d.ofCenter(pos))); } + /** + * Returns a sequence of random points dealed out to uniformly fill this shape's area. + */ + default Stream randomPoints(Random rand) { + return randomPoints((int)getVolume(), rand); + } + /** * Returns a new shape with after applying additional rotation. */ + @Override default Shape rotate(float pitch, float yaw) { - if (pitch == 0 && yaw == 0) { - return this; - } - return new RotatedShape(this, pitch, yaw); + return pitch == 0 && yaw == 0 ? this : new RotatedPointGenerator(this, pitch, yaw); } - /** - * Returns a new point generator where all of its points are offset by the specified amount. - */ @Override - default Shape offset(Vec3i offset) { - return offset(Vec3d.of(offset)); + default Shape translate(Vec3i offset) { + return offset.equals(Vec3i.ZERO) ? this : translate(Vec3d.of(offset)); } - /** - * Returns a new point generator where all of its points are offset by the specified amount. - */ @Override - default Shape offset(Vec3d offset) { - final Shape source = this; - return new Shape() { - @Override - public double getVolumeOfSpawnableSpace() { - return source.getVolumeOfSpawnableSpace(); - } - - @Override - public Vec3d computePoint(Random rand) { - return source.computePoint(rand).add(offset); - } - - @Override - public Stream getBlockPositions() { - return source.getBlockPositions().map(pos -> pos.add(offset.x, offset.y, offset.z)); - } - - @Override - public Vec3d getLowerBound() { - return source.getLowerBound().add(offset); - } - - @Override - public Vec3d getUpperBound() { - return source.getLowerBound().add(offset); - } - - @Override - public boolean isPointInside(Vec3d point) { - return source.isPointInside(point.subtract(offset)); - } - }; + default Shape translate(Vec3d offset) { + return offset.equals(Vec3d.ZERO) ? this : new TranslatedPointGenerator(this, offset); } } diff --git a/src/main/java/com/minelittlepony/unicopia/util/shape/Sphere.java b/src/main/java/com/minelittlepony/unicopia/util/shape/Sphere.java index d44f2c12..7ebf61af 100644 --- a/src/main/java/com/minelittlepony/unicopia/util/shape/Sphere.java +++ b/src/main/java/com/minelittlepony/unicopia/util/shape/Sphere.java @@ -48,19 +48,20 @@ public class Sphere implements Shape { } @Override - public double getVolumeOfSpawnableSpace() { + public double getVolume() { return volume; } private double computeSpawnableSpace() { - if (hollow) { - if (stretch.x == stretch.y && stretch.y == stretch.z) { - double radius = rad * stretch.x; - return 4 * Math.PI * radius * radius; - } - return computeEllipsoidArea(rad, stretch); + if (!hollow) { + return computeEllipsoidVolume(rad, stretch); } - return computeEllipsoidVolume(rad, stretch); + + if (stretch.x == stretch.y && stretch.y == stretch.z) { + double radius = rad * stretch.x; + return 4 * Math.PI * radius * radius; + } + return computeEllipsoidArea(rad, stretch); } @Override @@ -75,7 +76,11 @@ public class Sphere implements Shape { double phi = MathHelper.nextDouble(rand, 0, Math.PI * 2); double theta = Math.asin(z / rad); - return new Vec3d(rad * Math.cos(theta) * Math.cos(phi) * stretch.x, rad * Math.cos(theta) * Math.sin(phi) * stretch.y, z * stretch.z); + return new Vec3d( + rad * Math.cos(theta) * Math.cos(phi) * stretch.x, + rad * Math.cos(theta) * Math.sin(phi) * stretch.y, + z * stretch.z + ); } @Override @@ -89,12 +94,12 @@ public class Sphere implements Shape { @Override public Vec3d getLowerBound() { - return new Vec3d(-rad * stretch.x, -rad * stretch.y, -rad * stretch.z); + return stretch.multiply(-rad); } @Override public Vec3d getUpperBound() { - return new Vec3d(rad * stretch.x, rad * stretch.y, rad * stretch.z); + return stretch.multiply(rad); } public static double computeEllipsoidArea(double rad, Vec3d stretch) { diff --git a/src/main/java/com/minelittlepony/unicopia/util/shape/TranslatedPointGenerator.java b/src/main/java/com/minelittlepony/unicopia/util/shape/TranslatedPointGenerator.java new file mode 100644 index 00000000..a8031825 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/util/shape/TranslatedPointGenerator.java @@ -0,0 +1,43 @@ +package com.minelittlepony.unicopia.util.shape; + +import net.minecraft.util.math.Vec3d; +import net.minecraft.util.math.random.Random; + +record TranslatedPointGenerator ( + PointGenerator source, + Vec3d offset + ) implements Shape { + + @Override + public double getVolume() { + return ((Shape)source).getVolume(); + } + + @Override + public Vec3d computePoint(Random rand) { + return source.computePoint(rand).add(offset); + } + + @Override + public Vec3d getLowerBound() { + return ((Shape)source).getLowerBound().add(offset); + } + + @Override + public Vec3d getUpperBound() { + return ((Shape)source).getUpperBound().add(offset); + } + + @Override + public boolean isPointInside(Vec3d point) { + return ((Shape)source).isPointInside(point.subtract(offset)); + } + + @Override + public Shape translate(Vec3d offset) { + if (offset.equals(Vec3d.ZERO)) { + return this; + } + return new TranslatedPointGenerator(source, this.offset.add(offset)); + } +}