Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@ public static float sd(

var width = rect.z + ex;
var height = rect.w + ex;
final var hw = width * 0.5f;
final var hh = height * 0.5f;

var rotation = params.getRotation();
var radian = rotation * Mth.DEG_TO_RAD;
var cos = Mth.cos(radian);
var sin = Mth.sin(radian);

float cx;
float cy;
Expand All @@ -31,23 +38,17 @@ public static float sd(

} else {

cx = rect.x + width * 0.5f;
cy = rect.y + height * 0.5f;
cx = rect.x + hw - hw * cos + hh * sin;
cy = rect.y + hh - hw * sin - hh * cos;
}

var px = x - cx;
var py = y - cy;

var rotation = params.getRotation();
if (rotation != 0f) {

var r = -rotation * Mth.DEG_TO_RAD;

var s = (float)Math.sin(r);
var c = (float)Math.cos(r);

var tx = px * c - py * s;
var ty = px * s + py * c;
var tx = px * cos + py * sin;
var ty = py * cos - px * sin;

px = tx;
py = ty;
Expand Down Expand Up @@ -85,6 +86,12 @@ public static float sd(
px, py,
shape.x, shape.y,
shape.z
);

case SEGMENT -> sdSegment(
px, py,
shape.x, shape.y,
shape.z, shape.w
) - round;

case CAPSULE -> sdUnevenCapsule(
Expand All @@ -98,6 +105,20 @@ public static float sd(
shape.x, shape.y,
shape.z
);

case TRIANGLE_EQUILATERAL -> sdEquilateralTriangle(
px, py,
shape.x - round * 2.0f
) - round;

case TRIANGLE_ISOSCELES -> sdIsoscelesTriangle(
px,
py - (shape.y * 0.5f - round * 2.0f),
shape.x - round,
round * 2.0f - shape.y
) - round;

default -> Float.POSITIVE_INFINITY;
};

if (params.isOnion()) {
Expand Down Expand Up @@ -259,4 +280,85 @@ public static float sdEgg(
) - (ce + ra);
}

public static float sdSegment(
float px, float py,
float ax, float ay,
float bx, float by
) {
float bax = bx - ax;
float bay = by - ay;
float pax = px - ax;
float pay = py - ay;
float dot = pax * bax + pay * bay;
float h = Mth.clamp(
dot / (bax * bax + bay * bay),
0.0f,
1.0f
);

return Mth.length(
pax - h * bax,
pay - h * bay
);
}

public static float sdEquilateralTriangle(
float px, float py,
float r
) {
final float k = (float) Math.sqrt(3.0);

px = Math.abs(px) - r;
py = py + r / k;

if (px + k * py > 0.0f) {
var tx = (px - k * py) * 0.5f;
var ty = (-k * px - py) * 0.5f;
px = tx;
py = ty;
}

px -= Mth.clamp(px, -2.0f * r, 0.0f);

return -Mth.length(px, py) * Mth.sign(py);
}

public static float sdIsoscelesTriangle(
float px, float py,
float qx, float qy
) {
px = Math.abs(px);

float dotQ = qx * qx + qy * qy;
float h1 = Mth.clamp(
(px * qx + py * qy) / dotQ,
0.0f, 1.0f
);
float ax = px - qx * h1;
float ay = py - qy * h1;

float h2;
if (qx != 0.0f) {
h2 = Mth.clamp(px / qx, 0.0f, 1.0f);
} else {
h2 = px > 0.0f ? 1.0f : 0.0f;
}
float bx = px - qx * h2;
float by = py - qy;

float s = -Mth.sign(qy);

float da = ax * ax + ay * ay;
float sa = s * (px * qy - py * qx);

float db = bx * bx + by * by;
float sb = s * (py - qy);

float dDist = Math.min(da, db);
float dSign = Math.min(sa, sb);

return -(float) Math.sqrt(dDist)
* Mth.sign(dSign);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import net.neoforged.neoforge.client.event.ConfigureMainRenderTargetEvent;
import org.jetbrains.annotations.NotNull;
import org.joml.Matrix3x2f;
import org.joml.Vector3f;
import org.jspecify.annotations.NonNull;
import org.jspecify.annotations.Nullable;

Expand All @@ -37,6 +38,8 @@ public final class SdfGraphics {
@Getter
public static final SdfGraphics instance = new SdfGraphics(new SdfParameters());

private static boolean debug = false;

private final SdfParameters parameters;

public SdfGraphics box(float x, float y, float width, float height) {
Expand Down Expand Up @@ -109,6 +112,44 @@ public SdfGraphics egg(
return this;
}

public SdfGraphics segment(
float x0, float y0,
float x1, float y1
) {
var left = Math.min(x0, x1);
var top = Math.min(y0, y1);
var width = Math.abs(x1 - x0);
var height = Math.abs(y1 - y0);

var halfWidth = width * 0.5f;
var halfHeight = height * 0.5f;

this.parameters .getRect()
.set(left, top, width, height);
this.parameters .segment( -halfWidth, -halfHeight, +halfWidth, +halfHeight);

return this;
}

public SdfGraphics triangleEquilateral(float x, float y, float radius) {
var actual = radius * (1.0f / 1.2f);

this.parameters .getRect()
.set(x, y, radius * 2, radius * 2);
this.parameters .triangleEquilateral(actual);

return this;
}

public SdfGraphics triangleIsosceles(float x, float y, float width, float height) {
final var factor = 1.0f / 1.2f;
this.parameters .getRect()
.set(x, y, width * 2.0f, height);
this.parameters .triangleIsosceles(width * factor, height * factor);

return this;
}

public SdfGraphics color(int color) {
this.parameters .color(color);
return this;
Expand Down Expand Up @@ -207,6 +248,10 @@ public static void init(ConfigureMainRenderTargetEvent event) {
);
}

public static void debug(boolean enable) {
SdfGraphics.debug = enable;
}

private static void _draw(
@NotNull GuiGraphicsExtractor graphics,
@NotNull SdfParameters parameters
Expand All @@ -223,27 +268,52 @@ private static void _draw(
var ex = (round + smooth + stroke) * 2.0f;
var width = rect.z + ex;
var height = rect.w + ex;
final var hw = width * 0.5f;
final var hh = height * 0.5f;

final var rotation = parameters.getRotation();
final var radian = rotation * Mth.DEG_TO_RAD;
final var cos = Mth.cos(radian);
final var sin = Mth.sin(radian);

float cx;
float cy;
if (parameters.isCenter()) {
pose .translate(rect.x, rect.y);

cx = rect.x;
cy = rect.y;
} else {
pose .translate(
rect.x + width * 0.5f,
rect.y + height * 0.5f
rect.x + hw,
rect.y + hh
);

cx = rect.x + hw - hw * cos + hh * sin;
cy = rect.y + hh - hw * sin - hh * cos;
}

var x0 = -0.5f;
var y0 = -0.5f;
var x1 = +0.5f;
var y1 = +0.5f;
if (rotation != 0.0f) {
pose.rotate(Mth.DEG_TO_RAD * rotation);
}

pose .rotate(Mth.DEG_TO_RAD * parameters.getRotation())
.scale(width, height);
if (!parameters.isCenter()) {
pose .translate(-hw, -hh);
}

pose .scale(width, height);

rect.z = width;
rect.w = height;

var extX = Mth.abs(hw * cos) + Mth.abs(hh * sin) + 1.0f;
var extY = Mth.abs(hw * sin) + Mth.abs(hh * cos) + 1.0f;

var x0 = cx - extX;
var x1 = cx + extX;
var y0 = cy - extY;
var y1 = cy + extY;

var offset = index * SDF_PARAMETER_SIZE;
var slice = ubo.slice(offset, SDF_PARAMETER_SIZE);
var state = new RenderState(
Expand All @@ -256,10 +326,17 @@ private static void _draw(
null
);

if (debug) {
graphics.outline(
(int) x0, (int) y0,
(int) (x1 - x0), (int) (y1 - y0),
0xFF0000FF
);
}

parameters .upload(encoder, slice);

graphics .submitGuiElementRenderState(state);

rect.z = z;
rect.w = w;

Expand Down Expand Up @@ -313,10 +390,10 @@ private RenderState(

@Override
public void buildVertices(VertexConsumer consumer) {
consumer.addVertexWith2DPose(this.pose(), this.x0(), this.y0()).setUv(0, 0).setUv1(this.index(), 0).setColor(this.color());
consumer.addVertexWith2DPose(this.pose(), this.x0(), this.y1()).setUv(0, 1).setUv1(this.index(), 0).setColor(this.color());
consumer.addVertexWith2DPose(this.pose(), this.x1(), this.y1()).setUv(1, 1).setUv1(this.index(), 0).setColor(this.color());
consumer.addVertexWith2DPose(this.pose(), this.x1(), this.y0()).setUv(1, 0).setUv1(this.index(), 0).setColor(this.color());
consumer.addVertexWith2DPose(this.pose(), -0.5f, -0.5f).setUv(0, 0).setUv1(this.index(), 0).setColor(this.color());
consumer.addVertexWith2DPose(this.pose(), -0.5f, +0.5f).setUv(0, 1).setUv1(this.index(), 0).setColor(this.color());
consumer.addVertexWith2DPose(this.pose(), +0.5f, +0.5f).setUv(1, 1).setUv1(this.index(), 0).setColor(this.color());
consumer.addVertexWith2DPose(this.pose(), +0.5f, -0.5f).setUv(1, 0).setUv1(this.index(), 0).setColor(this.color());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,21 @@ public void egg(float topRadius, float bottomRadius, float height) {
this.shapeParams .set(height, bottomRadius, topRadius, 0.0f);
}

public void segment(float x0, float y0, float x1, float y1) {
this ._renderType(SdfRenderType.SEGMENT);
this.shapeParams .set(x0, y0, x1, y1);
}

public void triangleEquilateral(float radius) {
this ._renderType(SdfRenderType.TRIANGLE_EQUILATERAL);
this.shapeParams .set(radius, 0.0f, 0.0f, 0.0f);
}

public void triangleIsosceles(float base, float height) {
this ._renderType(SdfRenderType.TRIANGLE_ISOSCELES);
this.shapeParams .set(base, height, 0.0f, 0.0f);
}

public void smooth(float smooth) {
this ._smooth(smooth);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@ public enum SdfRenderType {
SECTOR,
PIE,
CAPSULE,
EGG;
EGG,
SEGMENT,

TRIANGLE_EQUILATERAL,
TRIANGLE_ISOSCELES,
;

private static final SdfRenderType[] VALUES = values();

Expand Down
Loading
Loading