korlibs / korge

KorGE Game Engine. Multiplatform Kotlin Game Engine
https://korge.org/
Other
2.41k stars 121 forks source link

PathMeasure implementation for VectorPath #609

Closed colinrgodsey closed 1 year ago

colinrgodsey commented 2 years ago

I'm working on an implementation of PathMeasure (in the skia style) for VectorPaths. We need this for a project we're working on, and I'm wondering if you'd like a PR for it? It's pretty valuable for path-based animations and a bunch of other cool stuff.

(BTW, thanks for all the KorLibs! Lot's of great stuff in here).

soywiz commented 2 years ago

I have implemented it recently; https://github.com/korlibs/korge-next/blob/09c2269571f8c7fb577bade1574deeca655e28cd/korma/src/commonMain/kotlin/com/soywiz/korma/geom/bezier/Bezier.kt#L39

colinrgodsey commented 2 years ago

ahh damn, that'll teach me for not looking at master. i'll keep an eye on the developments here. i'll get my implementation up to parity with skia and after the next korma release ill merge in, dedup, and see if anything is missing. closing for now!

soywiz commented 2 years ago

Actually it was dome super recently, and I was not aware that you were working on that :) of course any contribution is super welcome. So if you can check that implementation and if it lacks functionality you have implemented or have feedback based on your implementation feel free to give feedback/make PRs 👍

colinrgodsey commented 2 years ago

@soywiz sounds good! i'll open this back up for historical sake. here's the features im targeting:

soywiz commented 2 years ago

Cool! I have partially ported Bezier.JS: https://github.com/korlibs/korge-next/pull/716 to improve gpu vector rendering stuff since I need to improve how strokes are genreated. Feel free to keep track of the changes there. It already supports segmenting/simplification & splitting

colinrgodsey commented 2 years ago

oh awesome, yea that algorithm looks almost identical

soywiz commented 2 years ago

@colinrgodsey what does it mean transform matrix at distance? And contour splitting?

colinrgodsey commented 2 years ago

@soywiz It supports getting either: a) the position and tangent at some distance along the counter or b) the transform matrix at that point. The transform matrix is basically just packed the with the position as translation, and converts the tangent into the rotation components.

The contour splitting is pretty neat. Basically it walks each component of the contour, and for bezier curves, it splits the curves in half ("time"-wise) recursively until the segments are straight enough to be treated as lines for measurement sake. The segments store the "time" domain produced by the splitting, and uses those as a distance:time ratio when gathering sub-paths to help account for the time based splitting. The algorithm is taken directly from Skia, I just reproduced it using Korma paths. The test suite compares my implementation to Skia (via Skiko).

soywiz commented 2 years ago

@colinrgodsey

Okay, so let me explain the API that is already merged:

Bezier: https://github.com/korlibs/korge-next/blob/76f1835179e29e64c6adf58f0720d9b261dbd615/korma/src/commonMain/kotlin/com/soywiz/korma/geom/bezier/Bezier.kt handles a single curve. It supports getting the tangent/normal and position based on t. Then there is a LUT that allows to query for positions/info based on distance or by t. So you can get any value based on t and length and ratio. The transform matrix is not used here, so not provided, but I guess one could be easily use it. If you have an specific use-case, maybe it can be added. KorMA supports getting angles from vectors directly. You can split and get other operations.

Then there is a Curves class, that is a set of contiguous Bezier curves: https://github.com/korlibs/korge-next/blob/76f1835179e29e64c6adf58f0720d9b261dbd615/korma/src/commonMain/kotlin/com/soywiz/korma/geom/bezier/Curves.kt#L169-L171 Then there are functions to convert from/to VectorPath. And then there is code to convert a Path into a set of points for plotting a triangle strip: https://github.com/korlibs/korge-next/blob/76f1835179e29e64c6adf58f0720d9b261dbd615/korma/src/commonMain/kotlin/com/soywiz/korma/geom/bezier/CurvesToStroke.kt

Curves class also support splitting, and getting curve/t/tangent/normal/position based of length/ratio, and in fact splitting with that allows to do things like supporting creating dashed strokes.

soywiz commented 1 year ago

I belive this should be covered already. Feel free to reopen if you miss something