/** * NURBS curves and surfaces, and polyline ("Line") geometry. * * The basis evaluation and tessellation follow the FBX SDK conventions as implemented by ufbx: knot spans are * subdivided uniformly, closed and periodic curves wrap their control points, and surfaces are tessellated into * quads (degenerate quads at poles become triangles) with welded positions along the wrapped edges. */ import { type FBXNode } from "../types/fbxTypes.js"; import { type FBXGeometryData, type FBXGeometryDiagnostic } from "./geometry.js"; export type FBXNurbsTopology = "open" | "closed" | "periodic"; /** Knot vector and derived data of one parametric direction. */ export interface FBXNurbsBasis { order: number; topology: FBXNurbsTopology; knots: Float64Array; /** Parameter range that the curve is defined on */ tMin: number; tMax: number; /** Distinct knot values inside [tMin, tMax], i.e. the boundaries of the non-empty spans */ spans: Float64Array; /** False when the knot vector is too short or not monotonic */ valid: boolean; } /** NURBS curve: homogeneous control points (x, y, z, w) and a basis. */ export interface FBXNurbsCurveData { basis: FBXNurbsBasis; /** Control points as x,y,z,w */ controlPoints: Float64Array; numControlPoints: number; } /** NURBS surface: control points laid out as `v * numU + u`. */ export interface FBXNurbsSurfaceData { basisU: FBXNurbsBasis; basisV: FBXNurbsBasis; numU: number; numV: number; /** Control points as x,y,z,w */ controlPoints: Float64Array; flipNormals: boolean; /** Span subdivision stored in the file (Step), 0 when absent */ stepU: number; stepV: number; } /** Polyline geometry ready for a lines mesh: one or more open or closed point runs. */ export interface FBXCurveGeometryData { id: number; name: string; kind: "line" | "nurbsCurve"; /** Each polyline as x,y,z triples; closed runs repeat their first point at the end */ polylines: Float64Array[]; /** Display colour from the geometry's Color property */ color: [number, number, number] | null; diagnostics: FBXGeometryDiagnostic[]; } export declare function createNurbsBasis(order: number, form: string | undefined, knots: Float64Array): FBXNurbsBasis; /** * Evaluates the basis functions (and their derivatives) that are non-zero at `u`. * @returns index of the first influencing control point, or -1 when the basis cannot be evaluated */ export declare function evaluateNurbsBasis(basis: FBXNurbsBasis, u: number, weights: Float64Array, derivatives: Float64Array | null): number; /** Evaluates a curve point; `out` receives position (0..2) and derivative (3..5). */ export declare function evaluateNurbsCurve(curve: FBXNurbsCurveData, u: number, out: Float64Array, weights: Float64Array, derivs: Float64Array): boolean; /** Evaluates a surface point; `out` receives position (0..2), du (3..5) and dv (6..8). */ export declare function evaluateNurbsSurface(surface: FBXNurbsSurfaceData, u: number, v: number, out: Float64Array, scratch: { wu: Float64Array; wv: Float64Array; du: Float64Array; dv: Float64Array; }): boolean; /** * Tessellates a curve into a polyline with `subdivision` segments per knot span. Closed and periodic curves * end on a copy of their first point. */ export declare function tessellateNurbsCurve(curve: FBXNurbsCurveData, subdivision?: number): Float64Array | null; /** Span subdivision to use for a surface direction: an explicit override, else the file's Step, else 4. */ export declare function resolveSpanSubdivision(fileStep: number, override: number | undefined): number; /** * Tessellates a surface into triangles. Positions on wrapped (closed/periodic) edges and at poles are welded * exactly like the FBX SDK does, so degenerate quads collapse into triangles. */ export declare function tessellateNurbsSurface(surface: FBXNurbsSurfaceData, subU: number, subV: number): { positions: Float64Array; indices: Uint32Array; normals: Float64Array; uvs: Float64Array; } | null; /** Reads a NurbsCurve geometry node. */ export declare function extractNurbsCurve(node: FBXNode): FBXNurbsCurveData | null; /** Reads a NurbsSurface geometry node. */ export declare function extractNurbsSurface(node: FBXNode): FBXNurbsSurfaceData | null; /** Tessellates a NurbsSurface geometry node into mesh geometry. */ export declare function nurbsSurfaceToGeometry(node: FBXNode, geometryId: number, subdivisionOverride: number | undefined): FBXGeometryData | null; /** Reads a NurbsCurve geometry node into a tessellated polyline. */ export declare function extractNurbsCurveGeometry(node: FBXNode, geometryId: number, subdivision?: number): FBXCurveGeometryData; /** * Reads a Line geometry node: Points plus PointsIndex where a negative index (~index) ends a segment, as in * polygon vertex indices. */ export declare function extractLineGeometry(node: FBXNode, geometryId: number): FBXCurveGeometryData;