Editor Tool Utilities – Geometry
Comprehensive geometry utility library for spline-editing tools. Provides Catmull-Rom interpolation, Frenet frame computation, mouse-hit detection, vector math, polygon operations, and spline manipula
Comprehensive geometry utility library for spline-editing tools. Provides Catmull-Rom interpolation, Frenet frame computation, mouse-hit detection, vector math, polygon operations, and spline manipulation (split, join, flip, banking).
Public API
| Function | Signature | Description |
|---|---|---|
M.getPreRotQuats | () → table | Returns pre-computed rotation quaternions (0°, 90°, 180°, 270°) |
M.getBarScale | () → number | Returns the bar-point scale factor (0.5) |
M.squaredSegSegDist | (a0, a1, b0, b1, outP1, outP2) → number | Squared distance between two line segments; writes closest points |
M.isMouseOverNode | (splines) → bool, splineIdx, nodeIdx | Tests if mouse ray intersects any spline node sphere |
M.isMouseOverSpline | (spline, mousePos) → bool, segIdx, hitPt | Tests if mouse is over a spline via Catmull-Rom sampling |
M.isMouseOverPolyline | (points, mousePos) → bool, segIdx | Tests if mouse is near a 2D polyline |
M.isMouseOverRib | (splines) → bool, splineIdx, ribIdx | Tests if mouse is over a rib handle sphere |
M.isMouseOverBar | (splines) → bool, splineIdx, barIdx | Tests if mouse is over a bar handle sphere |
M.isMouseOverGraphNode | (nodes) → bool, key | Tests if mouse is over a navigation graph node |
M.getAABB | (points) → table | Returns axis-aligned bounding box {xMin,xMax,yMin,yMax} |
M.computeSplinePolygon | (spline, margin, polygon) | Computes a polygonal outline from a spline with margin |
M.isPointInTriangle | (p, a, b, c) → bool | Barycentric point-in-triangle test |
M.getTerrainNormal | (p) → vec3 | Returns terrain surface normal at world point |
M.getTerrainNormalInPlace | (p, out) | In-place terrain normal computation |
M.rotateVecAroundZ | (vec, v, angle) | Rotates vector around Z-axis in-place |
M.rotateVecAroundAxis | (v, k, theta) → vec3 | Rodrigues rotation around arbitrary axis |
M.rotateVecAroundAxisInlined | (v, k, theta, out) → vec3 | Non-allocating axis rotation |
M.computeTurningRadius | (p1, p2, p3) → number | Curvature radius from three points |
M.isLineSegIntersect | (a, b, c, d) → bool | Tests if two line segments intersect |
M.intersection2LineSegs | `(p1, p2, q1, q2, out) → vec3 | nil` |
M.angleBetweenVecsNorm | (a, b) → number | Angle between unit vectors (radians) |
M.angleBetweenVecs | (a, b) → number | Angle between arbitrary vectors |
M.angleBetweenVecs2D | (a, b) → number | Angle between vectors projected to XY plane |
M.signedAngleBetweenVecs | (a, b, axis) → number | Signed angle around axis (radians) |
M.signedAngleAroundAxis | (fromVec, toVec, axis) → number | Signed angle in degrees with plane projection |
M.intersectsUpQuadBarycentric | `(p, q) → number | false` |
M.pointInQuadBarycentric | (p, q) → bool | Tests if point is inside quadrilateral |
M.computeSourcesAABB | (sources) → table | AABB of source polyline collection |
M.getAllQuadrilaterals | (sources, margin) → table | Builds quadrilaterals from sources with lateral margin |
M.populateTreeQuads | (quads) → kdtree | Creates kd-tree from quadrilaterals |
M.splitSplineGeometry | (nodes, widths, nmls, splitIdx) → nodes1, w1, n1, nodes2, w2, n2 | Splits spline at node index |
M.splitLoopSplineGeometry | (nodes, widths, nmls, splitIdx) → nodesNew, wNew, nNew | Splits a loop spline, reordering geometry |
M.joinSplineGeometry | (n1, w1, nm1, idx1, n2, w2, nm2, idx2) → nodesNew, wNew, nNew | Joins two spline geometries |
M.flipSplineDirection | (spline) | Reverses spline node order in-place |
M.closestRibbonSegPointToPoint | (segIdx, ribbon, p) → vec3, distSq | Closest point on a ribbon segment |
M.getNodeSpansInsidePolygon | (nodes, polygon) → table | Returns spans of nodes inside a polygon |
M.projectPointToSpline | (pos, spline) → proj, s, t | Projects point onto spline; returns arc-length param |
M.sampleSpline | (divPts, tans, norms, spacing, ...) | Uniform arc-length sampling of a spline |
M.sampleSplineAdaptive | (divPts, tans, norms, meshLen, ...) | Curvature-adaptive spline sampling |
M.translateSpline | (pts, binormals, t, out) | Offsets spline laterally along binormals |
M.computeRandomJitterQuat_ZOnly | (jitter, nml, outQuat) → quat | Random Z-axis jitter quaternion |
M.computeRandomJitterQuat | (spline, tgt, right, nml, outQuat) → quat | Component-wise random jitter quaternion |
M.computeRandomJitterQuatFromFreedomAxes | (spline, axes, outQuat) → quat | Jitter from freedom axes |
M.updateRibPointsFree | (spline) | Recomputes rib points in free 3D space |
M.updateRibPointsRaycast | (spline) | Recomputes rib points with terrain conforming |
M.updateBarPoints | (spline, isBarsLimits) | Recomputes bar points from velocity data |
M.updateBarPointsGraph | (spline, graphData, isBarsLimit) | Recomputes bar points for graph paths |
M.computeSDF | (mask) → table | Signed distance field from binary mask |
M.getScanlineSpans | (gMinY, gMaxY, te, tb, polygon, xMin, xMax, y) | Scanline rasterisation of polygon |
M.catmullRomCentripetalFast | (p0, p1, p2, p3, t, s, out) → vec3 | Fast non-allocating centripetal Catmull-Rom |
M.catmullRomNodesOnly | (nodes, gran) → table | Interpolates nodes with Catmull-Rom |
M.catmullRomNodesWidthsOnly | (nodes, widths, gran, isLoop) → pts, wds | Interpolates nodes and widths |
M.catmullRomNodesWidthsVelVelLimits | (spline, gran) → pts, wds, vels, lims | Full property interpolation |
M.catmullRomRaycast | (spline, minDiv, minSpacing) | Catmull-Rom with vertical raycasting to terrain |
M.catmullRomConformToTerrain | (spline, minDiv) | Catmull-Rom with terrain height conforming |
M.catmullRomFree | (spline, minDiv) | Catmull-Rom in free 3D space with monotonic Z |
M.catmullRomFreeWithBanking | (spline, minDiv, bankStrength) | Free Catmull-Rom with auto-banking |
M.computeGraphPathFromNodes | (spline) | Populates spline geometry from nav graph path |
Code Examples
local geom = require('editor/toolUtilities/geom')
-- Check if mouse is hovering over any spline node
local splines = { mySpline1, mySpline2 }
local isOver, sIdx, nIdx = geom.isMouseOverNode(splines)
if isOver then
log('I', 'geom', 'Mouse over spline ' .. sIdx .. ', node ' .. nIdx)
end
-- Compute the AABB of a set of division points
local box = geom.getAABB(spline.divPoints)
log('I', 'geom', string.format('AABB: X[%.1f, %.1f] Y[%.1f, %.1f]',
box.xMin, box.xMax, box.yMin, box.yMax))
-- Generate secondary geometry from nodes using Catmull-Rom with raycast
geom.catmullRomRaycast(mySpline) -- populates divPoints, tangents, binormals, normals
-- Fast Catmull-Rom evaluation at a parameter
local out = vec3()
geom.catmullRomCentripetalFast(p0, p1, p2, p3, 0.5, 0.5, out)
-- Split a spline at node 5 into two halves
local n1, w1, nm1, n2, w2, nm2 = geom.splitSplineGeometry(
spline.nodes, spline.widths, spline.nmls, 5)
-- Compute turning radius from three consecutive points
local radius = geom.computeTurningRadius(nodes[3], nodes[4], nodes[5])
-- Project a world point onto a spline, get arc-length parameter
local proj, s, t = geom.projectPointToSpline(worldPos, spline)
if proj then
log('I', 'geom', string.format('Projected at s=%.3f, lateral t=%.3f', s, t))
end
-- Compute spline polygon outline for scanline operations
local polygon = {}
geom.computeSplinePolygon(spline, 5.0, polygon)
-- Update rib points with terrain conforming
geom.updateRibPointsRaycast(spline)
-- Update bar points from velocity data
geom.updateBarPoints(spline, false) -- false = use vels, true = use velLimits
-- Adaptive sampling along a spline (denser at high curvature)
local posns, tans, normals, scales = {}, {}, {}, {}
geom.sampleSplineAdaptive(spline.divPoints, spline.tangents, spline.normals,
meshLength, posns, tans, normals, scales)
-- Compute auto-banking with Catmull-Rom
geom.catmullRomFreeWithBanking(spline, 10, 0.8)
-- Populate nav graph path from selected graph nodes
geom.computeGraphPathFromNodes(spline)See Also
- Tool Utilities - Fit Polyline - Related reference
- Editor Tool Utilities – Gizmo - Related reference
- Editor Tool Utilities – Material Selection Manager - Related reference
- World Editor Guide - Guide
Tool Utilities - Fit Polyline
Fits a polyline to an unordered set of points by finding the optimal traversal order that maximises path smoothness and minimises distance.
Editor Tool Utilities – Gizmo
Utility module for managing the editor axis gizmo (translate/rotate) for spline-editing tools. Handles drag callbacks, undo/redo integration, and local/world alignment switching.