geometry library

CPU-side geometry: vertex layouts, mesh data, shape generators and the ray arithmetic that reads them.

A library of flutter3d_core, importable on its own. A modeller's editable mesh, the tool an agent speaks to and a bench compiled by dart compile exe all want to say MeshData without the renderer, and a caller that imports only this library gets only this library. It was flutter3d_geometry until the package boundary turned out to protect nothing a library does not.

DeviceMesh is not here. It is the rest of the geometry layer by subject matter, but it holds the one type that has met a device, so it lives with the renderer (src/engine/geometry/device_mesh.dart) and flutter3d_core.dart exports both.

Classes

CapsuleShape
Capsule: a cylinder of height closed by two hemispheres of radius.
CellGrid
columns by rows cells, each there or gone: a Space Invaders shield, a wall of bricks, a field of crops.
ConeShape
Cone with the apex at +Y: a cylinder whose top radius is zero.
CpuMesh
A mesh that lives only on the CPU.
CuboidShape
Axis-aligned box centred on the origin.
CylinderShape
Cylinder or truncated cone, centred on the origin, axis along Y.
DerivedShape
A shape defined by delegating to another one.
DiscShape
Flat annulus in the XZ plane facing +Y. An innerRadius of 0 gives a disc.
GeneratedTangents
What MeshTangents.generateTangents gives back: the mesh with its tangents, and for each vertex it appended at a mirrored seam, the vertex it copiedFrom.
LatheShape
A surface of revolution: a profile polyline swept around the Y axis.
LocalRay
A ray: an origin and a direction.
MeshBuilder
Accumulates vertices and indices into growing typed arrays.
MeshClusters
A mesh's index buffer read as consecutive runs of triangles, each with a box and a cone of normals — C9, for the scan or the CAD part too big to draw whole every frame.
MeshData
CPU-side geometry: interleaved vertices plus indices.
MeshGeometry
What the scene needs to know about a mesh, without knowing where it lives.
MorphBlend
Blends a mesh's morph targets into a copy of its vertices.
MorphTarget
One shape a mesh can be blended towards, as deltas from its base vertices.
MorphTexture
A mesh's morph deltas, packed the way lib/morph.glsl reads them.
OpenPath
A path through points, measured by distance along it: where it is at s metres, which way it runs there, and which way is right.
PackedIndices
Indices packed for GPU upload.
PlaneShape
Subdivided plane in the XZ plane, normal pointing at +Y.
Shape
A parameterized generator of geometry.
SphereShape
UV sphere, a revolved meridian arc.
TangentMethod
How MeshTangents.withGeneratedTangents derives a frame from the UVs.
TorusShape
Torus: a closed circular profile revolved around Y.
TriangleBvh
A bounding-volume hierarchy over the triangles of one mesh.
TriangleHit
Where a ray met a mesh, as TriangleBvh.raycast answers it: which triangle, in the mesh's own index order, how far along the ray, and the point.
VertexAttribute
Describes a single vertex attribute.
VertexFetchOrder
What optimizeVertexFetch answers: the renumbered indices, and for each old vertex its new index in oldToNew, for reordering the vertex data and anything held per vertex to match.
VertexLayout
An ordered set of attributes making up an interleaved vertex.

Extensions

MeshTangents on MeshData
Tangent generation, split out of MeshData because it is a self-contained algorithm that only ever touches MeshData's public surface — an extension keeps it that way rather than granting it access to private state it does not need.

Constants

defaultVertexCacheSize → const int
A FIFO post-transform vertex cache's own size on real GPUs, give or take — the number optimizeVertexCache scores triangle choices against when the caller does not name one.
neutralColor → const LinearColor
Opaque white: a vertex colour multiplies the surface, so this is the value that changes nothing.
noHit → const double
Returned instead of a distance when nothing was hit.

Properties

neutralJoints → Vector4
Every vertex bound to joint zero.
final
neutralTangent → Vector4
A unit tangent along +X with a positive bitangent sign.
final
neutralWeights → Vector4
All the influence on the first joint.
final

Functions

averageCacheMissRatio(Uint32List indices, {int cacheSize = defaultVertexCacheSize}) → double
Cache misses per triangle simulating a FIFO cache of cacheSize entries reading indices in order — the standard ACMR metric (Hoppe, "Optimization of Mesh Locality for Transparent Vertex Caching", 1999) for how well a triangle order reuses recently-transformed vertices.
buildPolyline(List<Vector3> points, {required double width, List<LinearColor>? colors, LinearColor? color, bool closed = false}) → MeshData
points as one band width pixels across, coloured per point.
optimizeTriangleOrder(Uint32List indices, int vertexCount, {int cacheSize = defaultVertexCacheSize}) → Uint32List
indices reordered so triangles sharing recently-drawn vertices are drawn near each other, by Forsyth's greedy scoring: each step emits the unemitted triangle whose three vertices score highest, then ages every vertex still in the simulated cache and rescores the triangles that touch it.
optimizeVertexCache(MeshData mesh, {int cacheSize = defaultVertexCacheSize}) → MeshData
mesh with its triangles and vertices reordered for GPU cache reuse: optimizeTriangleOrder on the index buffer, then optimizeVertexFetch to renumber vertices by first use in that new order — the same two-pass scheme real engines and meshoptimizer split into, because the two caches they target (post- and pre-transform) are optimized by different orders.
optimizeVertexFetch(Uint32List indices, int vertexCount) → VertexFetchOrder
indices renumbered so a vertex's new index is the order it is first referenced in — the pre-transform ("vertex fetch") half of GPU cache friendliness, meant to run on triangle-cache-ordered indices ( optimizeTriangleOrder's output) the way meshoptimizer's optVertexFetch follows its own optVertexCache. A vertex a GPU fetches right after the one before it in memory is a vertex its prefetcher already has queued; a triangle order optimized for the post-transform cache alone can still reference vertex data scattered across the buffer.
rayAabb(LocalRay ray, Aabb3 box) → double
Distance along ray to box, or noHit.
raySphere(LocalRay ray, Vector3 center, double radius) → double
Distance along ray to a sphere, or noHit. Inside counts as 0.
rayTriangle(LocalRay ray, Vector3 a, Vector3 b, Vector3 c, {Vector2? outUv, bool cullBackFace = false}) → double
Möller–Trumbore ray/triangle intersection.
ribbon(OpenPath path, {required double from, required double to, required double width, double step = 2.0}) → MeshData
The strip of road width metres across laid along path from from to to metres, cut every step metres: a flat mesh facing OpenPath.up, with texture u across the road and v along it in metres, so a repeating texture tiles at the same size on every piece.