From da8c5f73cf8442902d9eba26a545bb1f7af054e2 Mon Sep 17 00:00:00 2001 From: Shadowfacts Date: Mon, 21 Oct 2019 11:32:18 -0400 Subject: [PATCH] Basic bezier curve rendering --- .../shadowfacts/cacao/geometry/BezierCurve.kt | 49 +++++++++++++++++++ .../net/shadowfacts/cacao/geometry/Point.kt | 7 +++ .../shadowfacts/cacao/util/RenderHelper.kt | 9 ++++ .../shadowfacts/cacao/view/BezierCurveView.kt | 36 ++++++++++++++ 4 files changed, 101 insertions(+) create mode 100644 src/main/kotlin/net/shadowfacts/cacao/geometry/BezierCurve.kt create mode 100644 src/main/kotlin/net/shadowfacts/cacao/view/BezierCurveView.kt diff --git a/src/main/kotlin/net/shadowfacts/cacao/geometry/BezierCurve.kt b/src/main/kotlin/net/shadowfacts/cacao/geometry/BezierCurve.kt new file mode 100644 index 0000000..60a4453 --- /dev/null +++ b/src/main/kotlin/net/shadowfacts/cacao/geometry/BezierCurve.kt @@ -0,0 +1,49 @@ +package net.shadowfacts.cacao.geometry + +import java.lang.RuntimeException +import kotlin.math.pow + +/** + * Helper class that represents a cubic bezier curve. + * + * @author shadowfacts + */ +data class BezierCurve(private val points: Array) { + + init { + if (points.size != 4) { + throw RuntimeException("Cubic bezier curve must have exactly four points") + } + } + + fun point(time: Double): Point { + val x = coordinate(time, Axis.HORIZONTAL) + val y = coordinate(time, Axis.VERTICAL) + return Point(x, y) + } + + private fun coordinate(t: Double, axis: Axis): Double { + // B(t)=(1-t)^3*p0+3(1-t)^2*t*p1+3(1-t)*t^2*p2+t^3*p3 + val p0 = points[0][axis] + val p1 = points[1][axis] + val p2 = points[2][axis] + val p3 = points[3][axis] + return ((1 - t).pow(3) * p0) + (3 * (1 - t).pow(2) * t * p1) + (3 * (1 - t) * t.pow(2) * p2) + (t.pow(3) * p3) + } + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as BezierCurve + + if (!points.contentEquals(other.points)) return false + + return true + } + + override fun hashCode(): Int { + return points.contentHashCode() + } + +} \ No newline at end of file diff --git a/src/main/kotlin/net/shadowfacts/cacao/geometry/Point.kt b/src/main/kotlin/net/shadowfacts/cacao/geometry/Point.kt index f556a6a..81406d4 100644 --- a/src/main/kotlin/net/shadowfacts/cacao/geometry/Point.kt +++ b/src/main/kotlin/net/shadowfacts/cacao/geometry/Point.kt @@ -21,4 +21,11 @@ data class Point(val x: Double, val y: Double) { return Point(x - other.x, y - other.y) } + operator fun get(axis: Axis): Double { + return when (axis) { + Axis.HORIZONTAL -> x + Axis.VERTICAL -> y + } + } + } \ No newline at end of file diff --git a/src/main/kotlin/net/shadowfacts/cacao/util/RenderHelper.kt b/src/main/kotlin/net/shadowfacts/cacao/util/RenderHelper.kt index f041167..c858c11 100644 --- a/src/main/kotlin/net/shadowfacts/cacao/util/RenderHelper.kt +++ b/src/main/kotlin/net/shadowfacts/cacao/util/RenderHelper.kt @@ -9,6 +9,7 @@ import net.minecraft.client.render.VertexFormat import net.minecraft.client.render.VertexFormats import net.minecraft.client.sound.PositionedSoundInstance import net.minecraft.sound.SoundEvent +import net.shadowfacts.cacao.geometry.BezierCurve import net.shadowfacts.cacao.geometry.Point import net.shadowfacts.cacao.geometry.Rect import net.shadowfacts.cacao.util.texture.Texture @@ -108,6 +109,14 @@ object RenderHelper { GlStateManager.translated(x, y, z) } + /** + * @see org.lwjgl.opengl.GL11.glScaled + */ + fun scale(x: Double, y: Double, z: Double = 1.0) { + if (disabled) return + GlStateManager.scaled(x, y, z) + } + /** * @see org.lwjgl.opengl.GL11.glColor4f */ diff --git a/src/main/kotlin/net/shadowfacts/cacao/view/BezierCurveView.kt b/src/main/kotlin/net/shadowfacts/cacao/view/BezierCurveView.kt new file mode 100644 index 0000000..c026f70 --- /dev/null +++ b/src/main/kotlin/net/shadowfacts/cacao/view/BezierCurveView.kt @@ -0,0 +1,36 @@ +package net.shadowfacts.cacao.view + +import com.mojang.blaze3d.platform.GlStateManager +import net.shadowfacts.cacao.geometry.BezierCurve +import net.shadowfacts.cacao.geometry.Point +import net.shadowfacts.cacao.util.Color +import net.shadowfacts.cacao.util.RenderHelper + +/** + * @author shadowfacts + */ +class BezierCurveView(val curve: BezierCurve): View() { + + private val points by lazy { + val step = 0.05 + var t = 0.0 + val points = mutableListOf() + while (t <= 1) { + points.add(curve.point(t)) + t += step + } + points + } + + var lineWidth = 3f + var lineColor = Color.BLACK + + override fun drawContent(mouse: Point, delta: Float) { + RenderHelper.scale(bounds.width, bounds.height) + for ((index, point) in points.withIndex()) { + val next = points.getOrNull(index + 1) ?: break + RenderHelper.drawLine(point, next, zIndex, lineWidth, lineColor) + } + } + +} \ No newline at end of file