Skip to content

Commit b28cdd7

Browse files
committed
修改贝塞尔曲线的实现, 使得参数更符合网页生成
1 parent 351770a commit b28cdd7

3 files changed

Lines changed: 67 additions & 26 deletions

File tree

common/src/main/kotlin/cn/coostack/cooparticlesapi/annotations/codec/CodecHelper.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ object CodecHelper {
124124
)
125125
register(
126126
BlockPos::class.java,
127-
StreamCodec.of({ a, b -> BlockPos.STREAM_CODEC.encode(a, b) }, { BlockPos.STREAM_CODEC.decode(it) })
127+
StreamCodec.of(BlockPos.STREAM_CODEC::encode, BlockPos.STREAM_CODEC::decode)
128128
)
129129
register(
130130
BlockState::class.java,

common/src/main/kotlin/cn/coostack/cooparticlesapi/utils/Math3DUtil.kt

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1217,6 +1217,33 @@ object Math3DUtil {
12171217
}
12181218
}
12191219

1220+
fun evaluateBezierCurveYAtX(
1221+
target: RelativeLocation,
1222+
startHandle: RelativeLocation,
1223+
endHandle: RelativeLocation,
1224+
x: Double,
1225+
iterations: Int = 26
1226+
): Double {
1227+
if (target.x <= 0.0) return target.y
1228+
val actualX = x.coerceIn(0.0, target.x)
1229+
if (actualX <= 0.0) return 0.0
1230+
if (actualX >= target.x) return target.y
1231+
val end = target + endHandle
1232+
var lo = 0.0
1233+
var hi = 1.0
1234+
var mid = 0.5
1235+
repeat(iterations.coerceAtLeast(1)) {
1236+
mid = (lo + hi) * 0.5
1237+
val bx = cubicBezier(mid, 0.0, startHandle.x, end.x, target.x)
1238+
if (bx < actualX) {
1239+
lo = mid
1240+
} else {
1241+
hi = mid
1242+
}
1243+
}
1244+
return cubicBezier(mid, 0.0, startHandle.y, end.y, target.y)
1245+
}
1246+
12201247
fun cubicBezier(t: Double, p0: Double, p1: Double, p2: Double, p3: Double): Double {
12211248
val u = 1 - t
12221249
val u2 = u * u

common/src/main/kotlin/cn/coostack/cooparticlesapi/utils/helper/BezierValueScaleHelper.kt

Lines changed: 39 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -14,28 +14,47 @@ abstract class BezierValueScaleHelper(
1414
var controlPoint2: RelativeLocation
1515
) :
1616
ScaleHelper(minScale, maxScale, scaleTick) {
17-
private val deltaScale = maxScale - minScale
17+
private val deltaScale: Double
18+
get() = maxScale - minScale
1819

19-
var bezierPoints = Math3DUtil.generateBezierCurve(
20-
RelativeLocation(scaleTick.toDouble(), deltaScale, 0.0),
21-
controlPoint1, controlPoint2, scaleTick
22-
)
20+
var bezierPoints = createBezierPoints()
21+
22+
private fun createBezierPoints(): List<RelativeLocation> {
23+
val target = RelativeLocation(scaleTick.toDouble(), deltaScale, 0.0)
24+
val (startHandle, endHandle) = resolveControlPoints()
25+
return List(scaleTick + 1) { tick ->
26+
RelativeLocation(
27+
tick.toDouble(),
28+
Math3DUtil.evaluateBezierCurveYAtX(
29+
target,
30+
startHandle,
31+
endHandle,
32+
tick.toDouble()
33+
),
34+
0.0
35+
)
36+
}
37+
}
38+
39+
private fun resolveControlPoints(): Pair<RelativeLocation, RelativeLocation> {
40+
if (controlPoint2.x > 0.0 && controlPoint2.x <= scaleTick.toDouble()) {
41+
return RelativeLocation(controlPoint1.x, controlPoint1.y - minScale, controlPoint1.z) to
42+
RelativeLocation(controlPoint2.x - scaleTick, controlPoint2.y - maxScale, controlPoint2.z)
43+
}
44+
return controlPoint1.clone() to controlPoint2.clone()
45+
}
2346

2447
override fun recalculateStep(): BezierValueScaleHelper {
2548
val temp = min(minScale, maxScale)
2649
maxScale = max(minScale, maxScale)
2750
minScale = temp
28-
bezierPoints = Math3DUtil.generateBezierCurve(
29-
RelativeLocation(scaleTick.toDouble(), deltaScale, 0.0),
30-
controlPoint1, controlPoint2, scaleTick
31-
)
51+
bezierPoints = createBezierPoints()
3252
return this
3353
}
3454

3555
override fun toggleScale(scale: Double) {
36-
// 遍历scale?
3756
val currentPoint = bezierPoints.withIndex().minBy {
38-
abs(it.value.y - scale)
57+
abs(minScale + it.value.y - scale)
3958
}
4059
current = currentPoint.index
4160
scale(minScale + currentPoint.value.y)
@@ -44,23 +63,18 @@ abstract class BezierValueScaleHelper(
4463
override fun doScale() {
4564
if (getLoadedGroup() == null) return
4665
if (over()) return
47-
val value = bezierPoints[current++].y
48-
scale(minScale + value)
66+
current = (current + 1).coerceAtMost(scaleTick)
67+
scale(minScale + bezierPoints[current].y)
4968
}
5069

5170
override fun doScaleTo(current: Int) {
52-
val enter = current.coerceAtLeast(0)
71+
val enter = current.coerceIn(0, scaleTick)
5372
this.current = enter
54-
if (current >= scaleTick) {
55-
resetScaleMax()
56-
return
57-
}
58-
if (current <= 0) {
59-
resetScaleMin()
60-
return
73+
when {
74+
enter <= 0 -> scale(minScale)
75+
enter >= scaleTick -> scale(maxScale)
76+
else -> scale(minScale + bezierPoints[enter].y)
6177
}
62-
val value = bezierPoints[current].y
63-
scale(minScale + value)
6478
}
6579

6680
override fun doScaleReversed() {
@@ -70,7 +84,7 @@ abstract class BezierValueScaleHelper(
7084
if (isZero()) {
7185
return
7286
}
73-
val value = bezierPoints[max(0, --current)].y
74-
scale(minScale + value)
87+
current = max(0, current - 1)
88+
scale(minScale + bezierPoints[current].y)
7589
}
7690
}

0 commit comments

Comments
 (0)