|
TrackFlow Pro Documentation 1
Generate roller coasters, railroads, conveyors and more with a physics aware spline and meshing system.
|
This is a wrapper that treats an IArcLengthCurve as a Unity Spline. Here we mimic all of the functionality of Unity Splines but using the ArcFrame IArcLengthCurve on the backend. We do this so that we can leverage ArcFrame tools such as curvature continuity, native bishop frame integration, curve constraint solving methods, and more. More...
Classes | |
| struct | SegmentBuildState |
| Keep track of previous segment states in case the user wants to add a custom curve spec. More... | |
| struct | MutatorEntry |
| class | MutatorEntryComparer |
Public Member Functions | |
| bool | IsDrivenKnotPosition (int knotIndex) |
| If true, the knot position and end frame is driven by a curve spec (k, t, dk, and dt) AKA this segement was EXTRAPOLATED and not INTERPOLATED. | |
| bool | RegisterMutator (IPolylineMutator mutator, bool markDirty=true) |
| Register a mutator. Returns true if it was added, false if it was already registered or null. Call from OnEnable of the consumer script, and Unregister in OnDisable. | |
| bool | UnregisterMutator (IPolylineMutator mutator, bool markDirty=true) |
| Unregister a mutator. Returns true if removed, false if not found or null. | |
| void | EnsureBuilt () |
| Ensure we have a current built curve to reference. | |
| delegate void | PolylineMutator (ref ChordErrorSampler.Polyline poly) |
| Vector3 | EvaluatePosition (float t) |
| Evaluate a position along the spline given parameter t in [0, 1]. | |
| TrackFlowSample[] | GetAutoSamples () |
| Get a number of evenly spaced samples along the curve based on the quality settings. | |
| TrackFlowSample | Evaluate (float t) |
| Evaluate a normalized arc length between 0 and 1. | |
| void | BuildCurve (bool includeForcePreview=true) |
| void | PopulateForcePreviewSpeedProfileWithKnotKeyframes () |
| List< int > | BuildTrackSampleIndex (ChordErrorSampler.Polyline poly) |
| Build knotSampleIndex for whole-track modifiers. Each entry is the sample index where knot i starts. For closed tracks we also push a final 0 so the last segment is treated as going back to the start. | |
| bool | TryGetInheritedCurveSpecStart (int knotIndex, out double inheritedK0, out double inheritedTau0) |
| Get curvature and torsion values for driven knot endpoints. | |
| void | CullSamples (ref ChordErrorSampler.Polyline sampledCurve, int cullSamples=1) |
| Cull last few samples from a polyline, in case we want to ensure no duplicates exist at knot locations. | |
| void | AddControlPoint () |
| void | RemoveControlPointAt (int index) |
| void | SeverMesh () |
| void | OnDestroy () |
| Vector3 | KnotLocalToWorld (Vector3 localPos) |
| Vector3 | KnotWorldToLocal (Vector3 worldPos) |
| void | MarkDirty () |
| void | RebuildNow (bool includeForcePreview=true) |
| Force an immediate rebuild and clear the internal editor dirty flags. This avoids double-rebuilds when autoRebuildInEditor is enabled. | |
Public Attributes | |
| ForceComputeSettings | forceComputeSettings = ForceComputeSettings.Default(5f) |
| ForcePreviewSettings | forcePreview = new() |
| int | SplineRebuildRequests = 0 |
| bool | autoRebuildInEditor = true |
| Auto rebuild using the rebuild interval in the editor. | |
| float | autoRebuildInterval = 0.2f |
| float | Quality = 0.3f |
| Quality of the sampling mechanism. | |
| bool | Closed = false |
| Close the curve. | |
| bool | useSpline = true |
| Use spline mode instead of segment mode. | |
| SplineOptions | spline = new() |
| Spline mode options. | |
| TrackModifierOptions | trackModOptions = new() |
| Track modifier options. This controls rotation minimizing frame generation, roll profiles, offsets and orientations, etc. | |
| List< TrackFlowKnot > | ControlPoints = new() |
| Track control points. | |
Package Functions | |
| PolylineMutatorFlags | ApplyMutators (ref ChordErrorSampler.Polyline poly, in TrackContext trackCtx) |
| Applies all registered external mutators to the given polyline (in-place). Returns combined flags that describe what changed / what caches should be rebuilt. | |
| IArcLengthCurve | BuildSegment (int index, TrackFlowKnot sKnot, TrackFlowKnot eKnot, ref SegmentBuildState state, bool syncDrivenEndKnot=true) |
| Build an ArcFrame segment between two TrackFlowKnot. | |
Properties | |
| float | Length [get] |
| Curve length. | |
| Vector3[] | AutoPositions [get] |
| A cached list of automatically generated spline positions built with GetAutoPositions(). For visualization in the editor. | |
| ChordErrorSampler.Polyline | BasePolyline [get] |
| The polyline with no external mutators applied. | |
| ChordErrorSampler.Polyline | CurrentPolyline [get] |
| The polyline with all applied mutators. | |
| TrackContext | CurrentTrackContext [get] |
| bool | IsBuilt [get] |
| Current curve is built and accurate. | |
| bool | WantsHeavyPreview [get] |
| bool | IsDirty [get] |
| Editor-only: indicates whether the spline has pending changes that haven't been rebuilt. | |
Events | |
| EventHandler | OnSplineRebuilt |
| Subscribable event for when the spline is rebuilt, this is called after: | |
Private Member Functions | |
| Vector3[] | BuildPreviewPositionsFromPolyline () |
| Copy the polyline for previewing. | |
| void | RefreshPreviewPositionsFromPolyline () |
| TrackFlowSample[] | GetSamples (int numSamples) |
| Vector3[] | GetPositions (int numSamples) |
| void | EnsureSplineBuffers (int count) |
| void | ClearBuiltState (bool clearForcePreview=true) |
| void | ResolveCurveSpecConstructionFrame (TrackFlowKnot sKnot, CurveSpecOptions opts, out Vector3 T0, out Vector3 N0, out Vector3 B0) |
| Figure out which plane to apply curvature to. | |
| void | UpdateSegmentBuildState (IArcLengthCurve curve, ref SegmentBuildState state) |
| void | SyncDrivenEndKnotGeometry (TrackFlowKnot startKnot, TrackFlowKnot drivenKnot, IArcLengthCurve curve) |
| Sync the geometry of an intrinsic curve knot to the knot object. Do this because we can't control all aspects of the end frame when using Intrinsic Curves (Curve Spec segments). | |
| void | SyncDrivenEndKnotSolvedDisplayFrame (TrackFlowKnot drivenKnot, IArcLengthCurve curve) |
| Sync the display frame of the driven end knot to the knot object. | |
| void | OnValidate () |
| void | Update () |
| void | Start () |
| void | RebuiltEvent () |
| int | CatmullRomControlPoints (int knotCount, bool closed) |
| void | PrepareCatmullRomPoints3DFromKnots (IReadOnlyList< TrackFlowKnot > knots, bool closed, ref double[][] result) |
| int | BezierControlPoints (int knotCount, bool closed) |
| double[][] | PrepareBezierPoints3DFromKnots (IReadOnlyList< TrackFlowKnot > knots, bool closed, BezierOptions opts, ref double[][] result) |
| int | BSplineControlPoints (int knotCount, bool closed, int degree) |
| void | PrepareBSplinePoints3DFromKnots (IReadOnlyList< TrackFlowKnot > knots, bool closed, int degree, ref double[][] result) |
| Prepare control points for a B-spline track. For open curves, we build a clamped control net by repeating endpoints "degree" times. For closed curves, we append the first "degree" control points at the end for a periodic spline. | |
| int | HermiteControlPoints (int knotCount, bool closed) |
| void | PrepareHermitePoints3DFromKnots (IReadOnlyList< TrackFlowKnot > knots, bool closed, ref double[][] positions, ref double[][] tangents) |
| Prepare position and tangent arrays for a Hermite spline using all control points. For closed tracks, we duplicate the first point and tangent at the end so the curve can loop. | |
Static Private Member Functions | |
| static bool | AnimationCurveEquivalent (AnimationCurve a, AnimationCurve b) |
| static bool | ForceSettingsEquivalent (in ForceComputeSettings a, in ForceComputeSettings b) |
| static bool | CanReuseForceSamples (in ChordErrorSampler.Polyline prev, in ChordErrorSampler.Polyline curr, bool hasPrevSettings, in ForceComputeSettings prevSettings, in ForceComputeSettings currSettings) |
| static Quaternion | MinimalRotation (Vector3 fromT, Vector3 toT, Vector3 fallbackAxisHint) |
Private Attributes | |
| bool | _hasCachedForceSettings |
| ForceComputeSettings | _cachedForceSettings |
| double[][] | _splinePositions |
| reusable buffers for spline control points. may be redundant | |
| double[][] | _splineTangents |
| reusable buffers for spline tangents. | |
| bool | _dirty |
| int | _dirtyVersion |
| int | _lastBuiltVersion |
| float | _lastAutoRebuildTime |
| Vector3[] | _autoPositions = Array.Empty<Vector3>() |
| A cached list of automatically generated spline positions built with GetAutoPositions(). For visualization in the editor. | |
| readonly List< double > | _prefixes = new() |
| Each index contains the value of the arc length up to that knot index along the curve. | |
| readonly List< IArcLengthCurve > | _inners = new() |
| This holds our internal generated curves. | |
| List< SegmentContext > | currentSegmentContexts |
| TrackContext | currentTrackContext |
| ChordErrorSampler.Polyline | _finalPolyline |
| polyline with internal frame modifications + external mutators | |
| ChordErrorSampler.Polyline | _basePolyline |
| polyline with internal frame modifications | |
| readonly List< MutatorEntry > | _externalMutators = new(8) |
| int | _mutatorSequence |
| bool | _mutatorsNeedSort |
| bool | _isApplyingMutators |
| uint | _mutatorListVersion |
This is a wrapper that treats an IArcLengthCurve as a Unity Spline. Here we mimic all of the functionality of Unity Splines but using the ArcFrame IArcLengthCurve on the backend. We do this so that we can leverage ArcFrame tools such as curvature continuity, native bishop frame integration, curve constraint solving methods, and more.
Native Unity Splines only give you a BezierCurve between each knot,
in either linear, quadratic and cubic form, 3 choices. ArcFrame can give you Nth degree Bezier, as well as CatmullRom, B-Splines, Hermite Splines. ArcFrame does not just give you basis matrix splines either, it can give you any curve that can be described with a function in any dimension. For example ArcFrame can generate clothoids, aka Euler-spirals which are used extensively in real world road and track design. Now you can see why ArcFrame is a powerful tool compared to built in Splines. Since now you can design tracks with real world curvature aware banking adjustments, or drop a cube in the world and watch as the ArcFrameSpline automatically adjusts itself to avoid collision. <- can't do that yet but thats my goal
| void TrackFlowPro.Runtime.Core.Curves.TrackFlowSpline.AddControlPoint | ( | ) |
|
staticprivate |
|
package |
Applies all registered external mutators to the given polyline (in-place). Returns combined flags that describe what changed / what caches should be rebuilt.
|
private |
|
private |
| void TrackFlowPro.Runtime.Core.Curves.TrackFlowSpline.BuildCurve | ( | bool | includeForcePreview = true | ) |
|
private |
Copy the polyline for previewing.
|
package |
Build an ArcFrame segment between two TrackFlowKnot.
| sKnot | |
| eKnot |
| List< int > TrackFlowPro.Runtime.Core.Curves.TrackFlowSpline.BuildTrackSampleIndex | ( | ChordErrorSampler.Polyline | poly | ) |
Build knotSampleIndex for whole-track modifiers. Each entry is the sample index where knot i starts. For closed tracks we also push a final 0 so the last segment is treated as going back to the start.
| poly |
|
staticprivate |
|
private |
|
private |
| void TrackFlowPro.Runtime.Core.Curves.TrackFlowSpline.CullSamples | ( | ref ChordErrorSampler.Polyline | sampledCurve, |
| int | cullSamples = 1 ) |
Cull last few samples from a polyline, in case we want to ensure no duplicates exist at knot locations.
| sampledCurve |
| void TrackFlowPro.Runtime.Core.Curves.TrackFlowSpline.EnsureBuilt | ( | ) |
Ensure we have a current built curve to reference.
|
private |
| TrackFlowSample TrackFlowPro.Runtime.Core.Curves.TrackFlowSpline.Evaluate | ( | float | t | ) |
Evaluate a normalized arc length between 0 and 1.
| t |
| Vector3 TrackFlowPro.Runtime.Core.Curves.TrackFlowSpline.EvaluatePosition | ( | float | t | ) |
Evaluate a position along the spline given parameter t in [0, 1].
| t | A float in [0, 1] |
|
staticprivate |
| TrackFlowSample[] TrackFlowPro.Runtime.Core.Curves.TrackFlowSpline.GetAutoSamples | ( | ) |
Get a number of evenly spaced samples along the curve based on the quality settings.
|
private |
|
private |
|
private |
| bool TrackFlowPro.Runtime.Core.Curves.TrackFlowSpline.IsDrivenKnotPosition | ( | int | knotIndex | ) |
If true, the knot position and end frame is driven by a curve spec (k, t, dk, and dt) AKA this segement was EXTRAPOLATED and not INTERPOLATED.
| knotIndex |
| Vector3 TrackFlowPro.Runtime.Core.Curves.TrackFlowSpline.KnotLocalToWorld | ( | Vector3 | localPos | ) |
| Vector3 TrackFlowPro.Runtime.Core.Curves.TrackFlowSpline.KnotWorldToLocal | ( | Vector3 | worldPos | ) |
| void TrackFlowPro.Runtime.Core.Curves.TrackFlowSpline.MarkDirty | ( | ) |
|
staticprivate |
| void TrackFlowPro.Runtime.Core.Curves.TrackFlowSpline.OnDestroy | ( | ) |
|
private |
| delegate void TrackFlowPro.Runtime.Core.Curves.TrackFlowSpline.PolylineMutator | ( | ref ChordErrorSampler.Polyline | poly | ) |
| void TrackFlowPro.Runtime.Core.Curves.TrackFlowSpline.PopulateForcePreviewSpeedProfileWithKnotKeyframes | ( | ) |
|
private |
|
private |
Prepare control points for a B-spline track. For open curves, we build a clamped control net by repeating endpoints "degree" times. For closed curves, we append the first "degree" control points at the end for a periodic spline.
|
private |
| pts | |
| closed |
|
private |
Prepare position and tangent arrays for a Hermite spline using all control points. For closed tracks, we duplicate the first point and tangent at the end so the curve can loop.
| void TrackFlowPro.Runtime.Core.Curves.TrackFlowSpline.RebuildNow | ( | bool | includeForcePreview = true | ) |
Force an immediate rebuild and clear the internal editor dirty flags. This avoids double-rebuilds when autoRebuildInEditor is enabled.
|
private |
|
private |
| bool TrackFlowPro.Runtime.Core.Curves.TrackFlowSpline.RegisterMutator | ( | IPolylineMutator | mutator, |
| bool | markDirty = true ) |
Register a mutator. Returns true if it was added, false if it was already registered or null. Call from OnEnable of the consumer script, and Unregister in OnDisable.
| void TrackFlowPro.Runtime.Core.Curves.TrackFlowSpline.RemoveControlPointAt | ( | int | index | ) |
|
private |
Figure out which plane to apply curvature to.
| sKnot | |
| opts | |
| T0 | |
| N0 | |
| B0 |
| void TrackFlowPro.Runtime.Core.Curves.TrackFlowSpline.SeverMesh | ( | ) |
|
private |
|
private |
Sync the geometry of an intrinsic curve knot to the knot object. Do this because we can't control all aspects of the end frame when using Intrinsic Curves (Curve Spec segments).
| drivenKnot | |
| curve |
|
private |
Sync the display frame of the driven end knot to the knot object.
| drivenKnot | |
| curve |
| bool TrackFlowPro.Runtime.Core.Curves.TrackFlowSpline.TryGetInheritedCurveSpecStart | ( | int | knotIndex, |
| out double | inheritedK0, | ||
| out double | inheritedTau0 ) |
Get curvature and torsion values for driven knot endpoints.
| knotIndex | |
| inheritedK0 | |
| inheritedTau0 |
| bool TrackFlowPro.Runtime.Core.Curves.TrackFlowSpline.UnregisterMutator | ( | IPolylineMutator | mutator, |
| bool | markDirty = true ) |
Unregister a mutator. Returns true if removed, false if not found or null.
|
private |
|
private |
|
private |
A cached list of automatically generated spline positions built with GetAutoPositions(). For visualization in the editor.
|
private |
polyline with internal frame modifications
|
private |
|
private |
|
private |
|
private |
|
private |
polyline with internal frame modifications + external mutators
|
private |
|
private |
This holds our internal generated curves.
|
private |
|
private |
|
private |
|
private |
|
private |
|
private |
|
private |
Each index contains the value of the arc length up to that knot index along the curve.
|
private |
reusable buffers for spline control points. may be redundant
|
private |
reusable buffers for spline tangents.
| bool TrackFlowPro.Runtime.Core.Curves.TrackFlowSpline.autoRebuildInEditor = true |
Auto rebuild using the rebuild interval in the editor.
| float TrackFlowPro.Runtime.Core.Curves.TrackFlowSpline.autoRebuildInterval = 0.2f |
| bool TrackFlowPro.Runtime.Core.Curves.TrackFlowSpline.Closed = false |
Close the curve.
| List<TrackFlowKnot> TrackFlowPro.Runtime.Core.Curves.TrackFlowSpline.ControlPoints = new() |
Track control points.
|
private |
|
private |
| ForceComputeSettings TrackFlowPro.Runtime.Core.Curves.TrackFlowSpline.forceComputeSettings = ForceComputeSettings.Default(5f) |
| ForcePreviewSettings TrackFlowPro.Runtime.Core.Curves.TrackFlowSpline.forcePreview = new() |
| float TrackFlowPro.Runtime.Core.Curves.TrackFlowSpline.Quality = 0.3f |
Quality of the sampling mechanism.
| SplineOptions TrackFlowPro.Runtime.Core.Curves.TrackFlowSpline.spline = new() |
Spline mode options.
| int TrackFlowPro.Runtime.Core.Curves.TrackFlowSpline.SplineRebuildRequests = 0 |
| TrackModifierOptions TrackFlowPro.Runtime.Core.Curves.TrackFlowSpline.trackModOptions = new() |
Track modifier options. This controls rotation minimizing frame generation, roll profiles, offsets and orientations, etc.
| bool TrackFlowPro.Runtime.Core.Curves.TrackFlowSpline.useSpline = true |
Use spline mode instead of segment mode.
|
get |
A cached list of automatically generated spline positions built with GetAutoPositions(). For visualization in the editor.
|
get |
The polyline with no external mutators applied.
|
get |
The polyline with all applied mutators.
|
get |
|
get |
Current curve is built and accurate.
|
get |
Editor-only: indicates whether the spline has pending changes that haven't been rebuilt.
|
get |
Curve length.
|
get |
| EventHandler TrackFlowPro.Runtime.Core.Curves.TrackFlowSpline.OnSplineRebuilt |
Subscribable event for when the spline is rebuilt, this is called after: