diff --git a/src/main/java/ru/betterend/util/MHelper.java b/src/main/java/ru/betterend/util/MHelper.java index cd809279..537e4bf7 100644 --- a/src/main/java/ru/betterend/util/MHelper.java +++ b/src/main/java/ru/betterend/util/MHelper.java @@ -73,7 +73,15 @@ public class MHelper { return (float) Math.sqrt(x * x + y * y + z * z); } + public static float length(float x, float y) { + return (float) Math.sqrt(x * x + y * y); + } + public static float dot(float x1, float y1, float z1, float x2, float y2, float z2) { return x1 * x2 + y1 * y2 + z1 * z2; } + + public static float dot(float x1, float y1, float x2, float y2) { + return x1 * x2 + y1 * y2; + } } diff --git a/src/main/java/ru/betterend/util/sdf/primitive/SDFCapedCone.java b/src/main/java/ru/betterend/util/sdf/primitive/SDFCapedCone.java new file mode 100644 index 00000000..2028d8b1 --- /dev/null +++ b/src/main/java/ru/betterend/util/sdf/primitive/SDFCapedCone.java @@ -0,0 +1,51 @@ +package ru.betterend.util.sdf.primitive; + +import java.util.function.Function; + +import net.minecraft.block.BlockState; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import ru.betterend.util.MHelper; + +public class SDFCapedCone extends SDFPrimitive { + private float radius1; + private float radius2; + private float height; + + public SDFCapedCone(Function placerFunction) { + super(placerFunction); + } + + public SDFCapedCone(BlockState state) { + super(state); + } + + public SDFCapedCone setRadius1(float radius) { + this.radius1 = radius; + return this; + } + + public SDFCapedCone setRadius2(float radius) { + this.radius2 = radius; + return this; + } + + public SDFCapedCone setHeight(float height) { + this.height = height; + return this; + } + + @Override + public float getDistance(float x, float y, float z) { + float qx = MHelper.length(x, z);; + float k2x = radius2 - radius1; + float k2y = 2 * height; + float cax = qx - MHelper.min(qx, (y < 0F) ? radius1 : radius2); + float cay = Math.abs(y) - height; + float mlt = MathHelper.clamp(MHelper.dot(radius2 - qx, height - y, k2x, k2y) / MHelper.dot(k2x, k2y, k2x, k2y), 0F, 1F); + float cbx = qx - radius2 + k2x * mlt; + float cby = y - height + k2y * mlt; + float s = (cbx < 0F && cay < 0F) ? -1F : 1F; + return s * (float) Math.sqrt(MHelper.min(MHelper.dot(cax, cay, cax, cay), MHelper.dot(cbx, cby, cbx, cby))); + } +}