From 17663dac0276d51913a2bde52628101cfb5c339d Mon Sep 17 00:00:00 2001 From: paulevsGitch Date: Mon, 28 Sep 2020 20:31:10 +0300 Subject: [PATCH] Some SDF functions --- src/main/java/ru/betterend/util/MHelper.java | 12 +++++++++ src/main/java/ru/betterend/util/sdf/ISDF.java | 5 ++++ .../util/sdf/operator/SDFBinary.java | 18 +++++++++++++ .../util/sdf/operator/SDFIntersection.java | 12 +++++++++ .../betterend/util/sdf/operator/SDFScale.java | 23 +++++++++++++++++ .../sdf/operator/SDFSmoothIntersection.java | 20 +++++++++++++++ .../sdf/operator/SDFSmoothSubtraction.java | 20 +++++++++++++++ .../util/sdf/operator/SDFSmoothUnion.java | 20 +++++++++++++++ .../util/sdf/operator/SDFSubtraction.java | 12 +++++++++ .../betterend/util/sdf/operator/SDFUnion.java | 12 +++++++++ .../util/sdf/primitive/SDFCapsule.java | 25 +++++++++++++++++++ .../util/sdf/primitive/SDFSphere.java | 18 +++++++++++++ 12 files changed, 197 insertions(+) create mode 100644 src/main/java/ru/betterend/util/sdf/ISDF.java create mode 100644 src/main/java/ru/betterend/util/sdf/operator/SDFBinary.java create mode 100644 src/main/java/ru/betterend/util/sdf/operator/SDFIntersection.java create mode 100644 src/main/java/ru/betterend/util/sdf/operator/SDFScale.java create mode 100644 src/main/java/ru/betterend/util/sdf/operator/SDFSmoothIntersection.java create mode 100644 src/main/java/ru/betterend/util/sdf/operator/SDFSmoothSubtraction.java create mode 100644 src/main/java/ru/betterend/util/sdf/operator/SDFSmoothUnion.java create mode 100644 src/main/java/ru/betterend/util/sdf/operator/SDFSubtraction.java create mode 100644 src/main/java/ru/betterend/util/sdf/operator/SDFUnion.java create mode 100644 src/main/java/ru/betterend/util/sdf/primitive/SDFCapsule.java create mode 100644 src/main/java/ru/betterend/util/sdf/primitive/SDFSphere.java diff --git a/src/main/java/ru/betterend/util/MHelper.java b/src/main/java/ru/betterend/util/MHelper.java index 07de055f..1021fbf4 100644 --- a/src/main/java/ru/betterend/util/MHelper.java +++ b/src/main/java/ru/betterend/util/MHelper.java @@ -60,4 +60,16 @@ public class MHelper { public static int max(int a, int b) { return a > b ? a : b; } + + public static float min(float a, float b) { + return a < b ? a : b; + } + + public static float max(float a, float b) { + return a > b ? a : b; + } + + public static float length(float x, float y, float z) { + return (float) Math.sqrt(x * x + y * y + z * z); + } } diff --git a/src/main/java/ru/betterend/util/sdf/ISDF.java b/src/main/java/ru/betterend/util/sdf/ISDF.java new file mode 100644 index 00000000..83e91d21 --- /dev/null +++ b/src/main/java/ru/betterend/util/sdf/ISDF.java @@ -0,0 +1,5 @@ +package ru.betterend.util.sdf; + +public interface ISDF { + public float getDistance(float x, float y, float z); +} diff --git a/src/main/java/ru/betterend/util/sdf/operator/SDFBinary.java b/src/main/java/ru/betterend/util/sdf/operator/SDFBinary.java new file mode 100644 index 00000000..c7ae602c --- /dev/null +++ b/src/main/java/ru/betterend/util/sdf/operator/SDFBinary.java @@ -0,0 +1,18 @@ +package ru.betterend.util.sdf.operator; + +import ru.betterend.util.sdf.ISDF; + +public abstract class SDFBinary implements ISDF { + protected ISDF sourceA; + protected ISDF sourceB; + + public SDFBinary setSourceA(ISDF sourceA) { + this.sourceA = sourceA; + return this; + } + + public SDFBinary setSourceB(ISDF sourceB) { + this.sourceB = sourceB; + return this; + } +} diff --git a/src/main/java/ru/betterend/util/sdf/operator/SDFIntersection.java b/src/main/java/ru/betterend/util/sdf/operator/SDFIntersection.java new file mode 100644 index 00000000..c436921f --- /dev/null +++ b/src/main/java/ru/betterend/util/sdf/operator/SDFIntersection.java @@ -0,0 +1,12 @@ +package ru.betterend.util.sdf.operator; + +import ru.betterend.util.MHelper; + +public class SDFIntersection extends SDFBinary { + @Override + public float getDistance(float x, float y, float z) { + float a = this.sourceA.getDistance(x, y, z); + float b = this.sourceB.getDistance(x, y, z); + return MHelper.max(a, b); + } +} diff --git a/src/main/java/ru/betterend/util/sdf/operator/SDFScale.java b/src/main/java/ru/betterend/util/sdf/operator/SDFScale.java new file mode 100644 index 00000000..fa53f02d --- /dev/null +++ b/src/main/java/ru/betterend/util/sdf/operator/SDFScale.java @@ -0,0 +1,23 @@ +package ru.betterend.util.sdf.operator; + +import ru.betterend.util.sdf.ISDF; + +public class SDFScale implements ISDF { + private ISDF source; + private float scale; + + public SDFScale setSorce(ISDF source) { + this.source = source; + return this; + } + + public SDFScale setScale(float scale) { + this.scale = scale; + return this; + } + + @Override + public float getDistance(float x, float y, float z) { + return source.getDistance(x / scale, y / scale, z / scale) * scale; + } +} diff --git a/src/main/java/ru/betterend/util/sdf/operator/SDFSmoothIntersection.java b/src/main/java/ru/betterend/util/sdf/operator/SDFSmoothIntersection.java new file mode 100644 index 00000000..7ef2f4a6 --- /dev/null +++ b/src/main/java/ru/betterend/util/sdf/operator/SDFSmoothIntersection.java @@ -0,0 +1,20 @@ +package ru.betterend.util.sdf.operator; + +import net.minecraft.util.math.MathHelper; + +public class SDFSmoothIntersection extends SDFBinary { + private float radius; + + public SDFSmoothIntersection setRadius(float radius) { + this.radius = radius; + return this; + } + + @Override + public float getDistance(float x, float y, float z) { + float a = this.sourceA.getDistance(x, y, z); + float b = this.sourceB.getDistance(x, y, z); + float h = MathHelper.clamp(0.5F - 0.5F * (b - a) / radius, 0F, 1F); + return MathHelper.lerp(h, b, a) + radius * h * (1F - h); + } +} diff --git a/src/main/java/ru/betterend/util/sdf/operator/SDFSmoothSubtraction.java b/src/main/java/ru/betterend/util/sdf/operator/SDFSmoothSubtraction.java new file mode 100644 index 00000000..b9f9c1ae --- /dev/null +++ b/src/main/java/ru/betterend/util/sdf/operator/SDFSmoothSubtraction.java @@ -0,0 +1,20 @@ +package ru.betterend.util.sdf.operator; + +import net.minecraft.util.math.MathHelper; + +public class SDFSmoothSubtraction extends SDFBinary { + private float radius; + + public SDFSmoothSubtraction setRadius(float radius) { + this.radius = radius; + return this; + } + + @Override + public float getDistance(float x, float y, float z) { + float a = this.sourceA.getDistance(x, y, z); + float b = this.sourceB.getDistance(x, y, z); + float h = MathHelper.clamp(0.5F - 0.5F * (b + a) / radius, 0F, 1F); + return MathHelper.lerp(h, b, -a) + radius * h * (1F - h); + } +} diff --git a/src/main/java/ru/betterend/util/sdf/operator/SDFSmoothUnion.java b/src/main/java/ru/betterend/util/sdf/operator/SDFSmoothUnion.java new file mode 100644 index 00000000..4c553889 --- /dev/null +++ b/src/main/java/ru/betterend/util/sdf/operator/SDFSmoothUnion.java @@ -0,0 +1,20 @@ +package ru.betterend.util.sdf.operator; + +import net.minecraft.util.math.MathHelper; + +public class SDFSmoothUnion extends SDFBinary { + private float radius; + + public SDFSmoothUnion setRadius(float radius) { + this.radius = radius; + return this; + } + + @Override + public float getDistance(float x, float y, float z) { + float a = this.sourceA.getDistance(x, y, z); + float b = this.sourceB.getDistance(x, y, z); + float h = MathHelper.clamp(0.5F + 0.5F * (b - a) / radius, 0F, 1F); + return MathHelper.lerp(h, b, a) - radius * h * (1F - h); + } +} diff --git a/src/main/java/ru/betterend/util/sdf/operator/SDFSubtraction.java b/src/main/java/ru/betterend/util/sdf/operator/SDFSubtraction.java new file mode 100644 index 00000000..cb44d10d --- /dev/null +++ b/src/main/java/ru/betterend/util/sdf/operator/SDFSubtraction.java @@ -0,0 +1,12 @@ +package ru.betterend.util.sdf.operator; + +import ru.betterend.util.MHelper; + +public class SDFSubtraction extends SDFBinary { + @Override + public float getDistance(float x, float y, float z) { + float a = this.sourceA.getDistance(x, y, z); + float b = this.sourceB.getDistance(x, y, z); + return MHelper.max(-a, b); + } +} diff --git a/src/main/java/ru/betterend/util/sdf/operator/SDFUnion.java b/src/main/java/ru/betterend/util/sdf/operator/SDFUnion.java new file mode 100644 index 00000000..021c055e --- /dev/null +++ b/src/main/java/ru/betterend/util/sdf/operator/SDFUnion.java @@ -0,0 +1,12 @@ +package ru.betterend.util.sdf.operator; + +import ru.betterend.util.MHelper; + +public class SDFUnion extends SDFBinary { + @Override + public float getDistance(float x, float y, float z) { + float a = this.sourceA.getDistance(x, y, z); + float b = this.sourceB.getDistance(x, y, z); + return MHelper.min(a, b); + } +} diff --git a/src/main/java/ru/betterend/util/sdf/primitive/SDFCapsule.java b/src/main/java/ru/betterend/util/sdf/primitive/SDFCapsule.java new file mode 100644 index 00000000..f766744e --- /dev/null +++ b/src/main/java/ru/betterend/util/sdf/primitive/SDFCapsule.java @@ -0,0 +1,25 @@ +package ru.betterend.util.sdf.primitive; + +import net.minecraft.util.math.MathHelper; +import ru.betterend.util.MHelper; +import ru.betterend.util.sdf.ISDF; + +public class SDFCapsule implements ISDF { + private float radius; + private float height; + + public SDFCapsule setRadius(float radius) { + this.radius = radius; + return this; + } + + public SDFCapsule setHeight(float height) { + this.height = height; + return this; + } + + @Override + public float getDistance(float x, float y, float z) { + return MHelper.length(x, MathHelper.clamp(y, 0F, height), z) - radius; + } +} diff --git a/src/main/java/ru/betterend/util/sdf/primitive/SDFSphere.java b/src/main/java/ru/betterend/util/sdf/primitive/SDFSphere.java new file mode 100644 index 00000000..3b69a443 --- /dev/null +++ b/src/main/java/ru/betterend/util/sdf/primitive/SDFSphere.java @@ -0,0 +1,18 @@ +package ru.betterend.util.sdf.primitive; + +import ru.betterend.util.MHelper; +import ru.betterend.util.sdf.ISDF; + +public class SDFSphere implements ISDF { + private float radius; + + public SDFSphere setRadius(float radius) { + this.radius = radius; + return this; + } + + @Override + public float getDistance(float x, float y, float z) { + return MHelper.length(x, y, z) - radius; + } +}