Skip to content

chore: Write the Bézier math with vector operations and atan2 - #125

Merged
kous500 merged 1 commit into
mainfrom
chore/bezier-segment-math-20261114
Nov 14, 2026
Merged

kous500 merged 1 commit into
mainfrom
chore/bezier-segment-math-20261114

Conversation

@kous500

@kous500 kous500 commented Nov 14, 2026

Copy link
Copy Markdown
Owner

What and why

BezierSegment.angle found the direction of the curve with an expanded polynomial in t, written out once for x and once for z, and turned it into an angle with atan and its own cases for the quadrants. This makes the math read like the formulas it comes from.

  • Angle: Math.atan2(dx, dz) instead of atan(dx / dz) with cases for NaN and dz < 0. A zero vector still gives 0, as the Javadoc says; atan2 alone would give Math.PI or -Math.PI there when dz is -0.0. The Javadoc now gives the range, -Math.PI to Math.PI.
  • Direction: the derivative divided by 3, the steps between the points (step0 to step2) weighted by the quadratic Bernstein polynomials, instead of the expanded polynomial.
  • Names: the weights are named after their degree, cubic0 to cubic3 in point (bernstein0 to bernstein3 before) and quadratic0 to quadratic2 in angle.
  • Vector operations: Vector3.multiply(double) lets point and angle add weighted vectors instead of writing each coordinate.

Behavior:

  • point gives the same values: the products and the sums are made in the same order.
  • angle differs only in the last bits, and for directions towards -x and -z, where it now gives -π to -π/2 instead of π to 3π/2. The only caller, CurveLayout, uses its cosine and sine, which differ by at most about 7e-16. Compared with the previous code on 10 million random segments, the angle differs by at most 9.1e-13 radians where the direction is longer than 0.001.
  • When dz is -0.0, the previous code gave the opposite direction along x (-π/2 for +x); atan2 gives the right one. dz is -0.0 only when every term of it is.

How it was tested

  • ./gradlew build :curvebuilding-fabric:26.3:runGameTest checkCodeStyle --warning-mode all: the build and unit tests pass, with no Gradle, javac or Checkstyle warnings. The game tests pass on the six versions that build runs them on.
  • New tests: BezierSegmentTest checks the angle towards -x and -z (-3π/4), and Vector3Test checks multiply.
  • IntelliJ IDEA's inspections report no warnings in the changed files.
  • Not checked: //bc and the preview in the game, and the cost of the extra Vector3 objects in point, which the Fabric preview calls every frame.
  • Minecraft version: the versions of the game tests
  • Server software / loader: Fabric (game tests)
  • WorldEdit / FastAsyncWorldEdit version: the versions in the build

Notes

  • No changes for players or server owners beyond the rounding described above.

- BezierSegment.angle gets the angle with atan2 instead of atan and
  its own cases, and says that it is from -Math.PI to Math.PI. It is
  also right when dz is -0.0, where the atan version turned +x into -x.
- The direction is the derivative divided by 3: the steps between the
  points weighted by the quadratic Bernstein polynomials, instead of
  the expanded polynomial in t.
- The weights are named after their degree, cubic0 - cubic3 in point
  and quadratic0 - quadratic2 in angle.
- Vector3.multiply lets point and angle add weighted vectors. The sums
  are made in the same order as before.
@kous500
kous500 merged commit 9eeb650 into main Nov 14, 2026
28 checks passed
@kous500
kous500 deleted the chore/bezier-segment-math-20261114 branch November 14, 2026 13:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant