mirror of
https://github.com/Sollace/Unicopia.git
synced 2024-11-30 16:28:00 +01:00
Updates to the shape package
This commit is contained in:
parent
645d6c6b7e
commit
b8df7d0e67
19 changed files with 180 additions and 221 deletions
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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()))) {
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -34,7 +34,7 @@ public interface ParticleSource extends ParticleSpawner {
|
|||
}
|
||||
|
||||
default void spawnParticles(Vec3d pos, PointGenerator area, int count, Consumer<Vec3d> particleSpawner) {
|
||||
area.offset(pos).randomPoints(count, getReferenceWorld().random).forEach(particleSpawner);
|
||||
area.translate(pos).randomPoints(count, getReferenceWorld().random).forEach(particleSpawner);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<Vec3d> randomPoints(Random rand) {
|
||||
return randomPoints((int)getVolumeOfSpawnableSpace(), rand);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a sequence of N random points.
|
||||
*/
|
||||
default Stream<Vec3d> randomPoints(int n, Random rand) {
|
||||
AtomicInteger atom = new AtomicInteger(n);
|
||||
return StreamSupport.stream(new AbstractSpliterator<Vec3d>(n, Spliterator.SIZED) {
|
||||
private int index = n;
|
||||
|
||||
@Override
|
||||
public boolean tryAdvance(Consumer<? super Vec3d> 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<BlockPos> 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<BlockPos> 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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<BlockPos> 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<Vec3d> 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<BlockPos> 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue