355 lines
		
	
	
	
		
			9.9 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			355 lines
		
	
	
	
		
			9.9 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
| package net.minecraft.world.phys;
 | |
| 
 | |
| import com.mojang.serialization.Codec;
 | |
| import io.netty.buffer.ByteBuf;
 | |
| import java.util.EnumSet;
 | |
| import java.util.List;
 | |
| import net.minecraft.Util;
 | |
| import net.minecraft.core.Direction;
 | |
| import net.minecraft.core.Position;
 | |
| import net.minecraft.core.Vec3i;
 | |
| import net.minecraft.network.FriendlyByteBuf;
 | |
| import net.minecraft.network.codec.StreamCodec;
 | |
| import net.minecraft.util.Mth;
 | |
| import net.minecraft.util.RandomSource;
 | |
| import org.joml.Vector3f;
 | |
| 
 | |
| public class Vec3 implements Position {
 | |
| 	public static final Codec<Vec3> CODEC = Codec.DOUBLE
 | |
| 		.listOf()
 | |
| 		.comapFlatMap(
 | |
| 			list -> Util.fixedSize(list, 3).map(listx -> new Vec3((Double)listx.get(0), (Double)listx.get(1), (Double)listx.get(2))),
 | |
| 			vec3 -> List.of(vec3.x(), vec3.y(), vec3.z())
 | |
| 		);
 | |
| 	public static final StreamCodec<ByteBuf, Vec3> STREAM_CODEC = new StreamCodec<ByteBuf, Vec3>() {
 | |
| 		public Vec3 decode(ByteBuf byteBuf) {
 | |
| 			return FriendlyByteBuf.readVec3(byteBuf);
 | |
| 		}
 | |
| 
 | |
| 		public void encode(ByteBuf byteBuf, Vec3 vec3) {
 | |
| 			FriendlyByteBuf.writeVec3(byteBuf, vec3);
 | |
| 		}
 | |
| 	};
 | |
| 	public static final Vec3 ZERO = new Vec3(0.0, 0.0, 0.0);
 | |
| 	public final double x;
 | |
| 	public final double y;
 | |
| 	public final double z;
 | |
| 
 | |
| 	public static Vec3 fromRGB24(int packed) {
 | |
| 		double d = (packed >> 16 & 0xFF) / 255.0;
 | |
| 		double e = (packed >> 8 & 0xFF) / 255.0;
 | |
| 		double f = (packed & 0xFF) / 255.0;
 | |
| 		return new Vec3(d, e, f);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Copies the coordinates of an int vector exactly.
 | |
| 	 */
 | |
| 	public static Vec3 atLowerCornerOf(Vec3i toCopy) {
 | |
| 		return new Vec3(toCopy.getX(), toCopy.getY(), toCopy.getZ());
 | |
| 	}
 | |
| 
 | |
| 	public static Vec3 atLowerCornerWithOffset(Vec3i toCopy, double offsetX, double offsetY, double offsetZ) {
 | |
| 		return new Vec3(toCopy.getX() + offsetX, toCopy.getY() + offsetY, toCopy.getZ() + offsetZ);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Copies the coordinates of an Int vector and centers them.
 | |
| 	 */
 | |
| 	public static Vec3 atCenterOf(Vec3i toCopy) {
 | |
| 		return atLowerCornerWithOffset(toCopy, 0.5, 0.5, 0.5);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Copies the coordinates of an int vector and centers them horizontally (x and z)
 | |
| 	 */
 | |
| 	public static Vec3 atBottomCenterOf(Vec3i toCopy) {
 | |
| 		return atLowerCornerWithOffset(toCopy, 0.5, 0.0, 0.5);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Copies the coordinates of an int vector and centers them horizontally and applies a vertical offset.
 | |
| 	 */
 | |
| 	public static Vec3 upFromBottomCenterOf(Vec3i toCopy, double verticalOffset) {
 | |
| 		return atLowerCornerWithOffset(toCopy, 0.5, verticalOffset, 0.5);
 | |
| 	}
 | |
| 
 | |
| 	public Vec3(double x, double y, double z) {
 | |
| 		this.x = x;
 | |
| 		this.y = y;
 | |
| 		this.z = z;
 | |
| 	}
 | |
| 
 | |
| 	public Vec3(Vector3f vector) {
 | |
| 		this(vector.x(), vector.y(), vector.z());
 | |
| 	}
 | |
| 
 | |
| 	public Vec3(Vec3i vector) {
 | |
| 		this(vector.getX(), vector.getY(), vector.getZ());
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Returns a new vector with the result of the specified vector minus this.
 | |
| 	 */
 | |
| 	public Vec3 vectorTo(Vec3 vec) {
 | |
| 		return new Vec3(vec.x - this.x, vec.y - this.y, vec.z - this.z);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Normalizes the vector to a length of 1 (except if it is the zero vector)
 | |
| 	 */
 | |
| 	public Vec3 normalize() {
 | |
| 		double d = Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);
 | |
| 		return d < 1.0E-5F ? ZERO : new Vec3(this.x / d, this.y / d, this.z / d);
 | |
| 	}
 | |
| 
 | |
| 	public double dot(Vec3 vec) {
 | |
| 		return this.x * vec.x + this.y * vec.y + this.z * vec.z;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Returns a new vector with the result of this vector x the specified vector.
 | |
| 	 */
 | |
| 	public Vec3 cross(Vec3 vec) {
 | |
| 		return new Vec3(this.y * vec.z - this.z * vec.y, this.z * vec.x - this.x * vec.z, this.x * vec.y - this.y * vec.x);
 | |
| 	}
 | |
| 
 | |
| 	public Vec3 subtract(Vec3 vec) {
 | |
| 		return this.subtract(vec.x, vec.y, vec.z);
 | |
| 	}
 | |
| 
 | |
| 	public Vec3 subtract(double amount) {
 | |
| 		return this.subtract(amount, amount, amount);
 | |
| 	}
 | |
| 
 | |
| 	public Vec3 subtract(double x, double y, double z) {
 | |
| 		return this.add(-x, -y, -z);
 | |
| 	}
 | |
| 
 | |
| 	public Vec3 add(double amount) {
 | |
| 		return this.add(amount, amount, amount);
 | |
| 	}
 | |
| 
 | |
| 	public Vec3 add(Vec3 vec) {
 | |
| 		return this.add(vec.x, vec.y, vec.z);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Adds the specified x,y,z vector components to this vector and returns the resulting vector. Does not change this vector.
 | |
| 	 */
 | |
| 	public Vec3 add(double x, double y, double z) {
 | |
| 		return new Vec3(this.x + x, this.y + y, this.z + z);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Checks if a position is within a certain distance of the coordinates.
 | |
| 	 */
 | |
| 	public boolean closerThan(Position pos, double distance) {
 | |
| 		return this.distanceToSqr(pos.x(), pos.y(), pos.z()) < distance * distance;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Euclidean distance between this and the specified vector, returned as double.
 | |
| 	 */
 | |
| 	public double distanceTo(Vec3 vec) {
 | |
| 		double d = vec.x - this.x;
 | |
| 		double e = vec.y - this.y;
 | |
| 		double f = vec.z - this.z;
 | |
| 		return Math.sqrt(d * d + e * e + f * f);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * The square of the Euclidean distance between this and the specified vector.
 | |
| 	 */
 | |
| 	public double distanceToSqr(Vec3 vec) {
 | |
| 		double d = vec.x - this.x;
 | |
| 		double e = vec.y - this.y;
 | |
| 		double f = vec.z - this.z;
 | |
| 		return d * d + e * e + f * f;
 | |
| 	}
 | |
| 
 | |
| 	public double distanceToSqr(double x, double y, double z) {
 | |
| 		double d = x - this.x;
 | |
| 		double e = y - this.y;
 | |
| 		double f = z - this.z;
 | |
| 		return d * d + e * e + f * f;
 | |
| 	}
 | |
| 
 | |
| 	public boolean closerThan(Vec3 pos, double horizontalDistance, double verticalDistance) {
 | |
| 		double d = pos.x() - this.x;
 | |
| 		double e = pos.y() - this.y;
 | |
| 		double f = pos.z() - this.z;
 | |
| 		return Mth.lengthSquared(d, f) < Mth.square(horizontalDistance) && Math.abs(e) < verticalDistance;
 | |
| 	}
 | |
| 
 | |
| 	public Vec3 scale(double factor) {
 | |
| 		return this.multiply(factor, factor, factor);
 | |
| 	}
 | |
| 
 | |
| 	public Vec3 reverse() {
 | |
| 		return this.scale(-1.0);
 | |
| 	}
 | |
| 
 | |
| 	public Vec3 multiply(Vec3 vec) {
 | |
| 		return this.multiply(vec.x, vec.y, vec.z);
 | |
| 	}
 | |
| 
 | |
| 	public Vec3 multiply(double factorX, double factorY, double factorZ) {
 | |
| 		return new Vec3(this.x * factorX, this.y * factorY, this.z * factorZ);
 | |
| 	}
 | |
| 
 | |
| 	public Vec3 horizontal() {
 | |
| 		return new Vec3(this.x, 0.0, this.z);
 | |
| 	}
 | |
| 
 | |
| 	public Vec3 offsetRandom(RandomSource random, float factor) {
 | |
| 		return this.add((random.nextFloat() - 0.5F) * factor, (random.nextFloat() - 0.5F) * factor, (random.nextFloat() - 0.5F) * factor);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Returns the length of the vector.
 | |
| 	 */
 | |
| 	public double length() {
 | |
| 		return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);
 | |
| 	}
 | |
| 
 | |
| 	public double lengthSqr() {
 | |
| 		return this.x * this.x + this.y * this.y + this.z * this.z;
 | |
| 	}
 | |
| 
 | |
| 	public double horizontalDistance() {
 | |
| 		return Math.sqrt(this.x * this.x + this.z * this.z);
 | |
| 	}
 | |
| 
 | |
| 	public double horizontalDistanceSqr() {
 | |
| 		return this.x * this.x + this.z * this.z;
 | |
| 	}
 | |
| 
 | |
| 	public boolean equals(Object object) {
 | |
| 		if (this == object) {
 | |
| 			return true;
 | |
| 		} else if (!(object instanceof Vec3 vec3)) {
 | |
| 			return false;
 | |
| 		} else if (Double.compare(vec3.x, this.x) != 0) {
 | |
| 			return false;
 | |
| 		} else {
 | |
| 			return Double.compare(vec3.y, this.y) != 0 ? false : Double.compare(vec3.z, this.z) == 0;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	public int hashCode() {
 | |
| 		long l = Double.doubleToLongBits(this.x);
 | |
| 		int i = (int)(l ^ l >>> 32);
 | |
| 		l = Double.doubleToLongBits(this.y);
 | |
| 		i = 31 * i + (int)(l ^ l >>> 32);
 | |
| 		l = Double.doubleToLongBits(this.z);
 | |
| 		return 31 * i + (int)(l ^ l >>> 32);
 | |
| 	}
 | |
| 
 | |
| 	public String toString() {
 | |
| 		return "(" + this.x + ", " + this.y + ", " + this.z + ")";
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Lerps between this vector and the given vector.
 | |
| 	 * @see net.minecraft.util.Mth#lerp(double, double, double)
 | |
| 	 */
 | |
| 	public Vec3 lerp(Vec3 to, double delta) {
 | |
| 		return new Vec3(Mth.lerp(delta, this.x, to.x), Mth.lerp(delta, this.y, to.y), Mth.lerp(delta, this.z, to.z));
 | |
| 	}
 | |
| 
 | |
| 	public Vec3 xRot(float pitch) {
 | |
| 		float f = Mth.cos(pitch);
 | |
| 		float g = Mth.sin(pitch);
 | |
| 		double d = this.x;
 | |
| 		double e = this.y * f + this.z * g;
 | |
| 		double h = this.z * f - this.y * g;
 | |
| 		return new Vec3(d, e, h);
 | |
| 	}
 | |
| 
 | |
| 	public Vec3 yRot(float yaw) {
 | |
| 		float f = Mth.cos(yaw);
 | |
| 		float g = Mth.sin(yaw);
 | |
| 		double d = this.x * f + this.z * g;
 | |
| 		double e = this.y;
 | |
| 		double h = this.z * f - this.x * g;
 | |
| 		return new Vec3(d, e, h);
 | |
| 	}
 | |
| 
 | |
| 	public Vec3 zRot(float roll) {
 | |
| 		float f = Mth.cos(roll);
 | |
| 		float g = Mth.sin(roll);
 | |
| 		double d = this.x * f + this.y * g;
 | |
| 		double e = this.y * f - this.x * g;
 | |
| 		double h = this.z;
 | |
| 		return new Vec3(d, e, h);
 | |
| 	}
 | |
| 
 | |
| 	public Vec3 rotateClockwise90() {
 | |
| 		return new Vec3(-this.z, this.y, this.x);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Returns a {@link net.minecraft.world.phys.Vec3} from the given pitch and yaw degrees as {@link net.minecraft.world.phys.Vec2}.
 | |
| 	 */
 | |
| 	public static Vec3 directionFromRotation(Vec2 vec) {
 | |
| 		return directionFromRotation(vec.x, vec.y);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Returns a {@link net.minecraft.world.phys.Vec3} from the given pitch and yaw degrees.
 | |
| 	 */
 | |
| 	public static Vec3 directionFromRotation(float pitch, float yaw) {
 | |
| 		float f = Mth.cos(-yaw * (float) (Math.PI / 180.0) - (float) Math.PI);
 | |
| 		float g = Mth.sin(-yaw * (float) (Math.PI / 180.0) - (float) Math.PI);
 | |
| 		float h = -Mth.cos(-pitch * (float) (Math.PI / 180.0));
 | |
| 		float i = Mth.sin(-pitch * (float) (Math.PI / 180.0));
 | |
| 		return new Vec3(g * h, i, f * h);
 | |
| 	}
 | |
| 
 | |
| 	public Vec3 align(EnumSet<Direction.Axis> axes) {
 | |
| 		double d = axes.contains(Direction.Axis.X) ? Mth.floor(this.x) : this.x;
 | |
| 		double e = axes.contains(Direction.Axis.Y) ? Mth.floor(this.y) : this.y;
 | |
| 		double f = axes.contains(Direction.Axis.Z) ? Mth.floor(this.z) : this.z;
 | |
| 		return new Vec3(d, e, f);
 | |
| 	}
 | |
| 
 | |
| 	public double get(Direction.Axis axis) {
 | |
| 		return axis.choose(this.x, this.y, this.z);
 | |
| 	}
 | |
| 
 | |
| 	public Vec3 with(Direction.Axis axis, double length) {
 | |
| 		double d = axis == Direction.Axis.X ? length : this.x;
 | |
| 		double e = axis == Direction.Axis.Y ? length : this.y;
 | |
| 		double f = axis == Direction.Axis.Z ? length : this.z;
 | |
| 		return new Vec3(d, e, f);
 | |
| 	}
 | |
| 
 | |
| 	public Vec3 relative(Direction direction, double length) {
 | |
| 		Vec3i vec3i = direction.getUnitVec3i();
 | |
| 		return new Vec3(this.x + length * vec3i.getX(), this.y + length * vec3i.getY(), this.z + length * vec3i.getZ());
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public final double x() {
 | |
| 		return this.x;
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public final double y() {
 | |
| 		return this.y;
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public final double z() {
 | |
| 		return this.z;
 | |
| 	}
 | |
| 
 | |
| 	public Vector3f toVector3f() {
 | |
| 		return new Vector3f((float)this.x, (float)this.y, (float)this.z);
 | |
| 	}
 | |
| 
 | |
| 	public Vec3 projectedOn(Vec3 vector) {
 | |
| 		return vector.lengthSqr() == 0.0 ? vector : vector.scale(this.dot(vector)).scale(1.0 / vector.lengthSqr());
 | |
| 	}
 | |
| }
 |