class MAGES::MeshDeformations::PerTriangleAtlas

Overview

Per-triangle UV atlas generator for fully split triangular meshes. Unlike AutoUV’s cardinal box projection, every real boundary triangle owns a disjoint atlas cell, so there are no holes by construction and no cardinal-projection overlap/starvation in concave pockets. More…

class PerTriangleAtlas
{
public:
    // methods

    static float2[] Generate(
        float3[] vertices,
        int[] indices,
        float padding,
        float minCellUv,
        bool assumeHull = true
    );
};

Detailed Documentation

Per-triangle UV atlas generator for fully split triangular meshes. Unlike AutoUV’s cardinal box projection, every real boundary triangle owns a disjoint atlas cell, so there are no holes by construction and no cardinal-projection overlap/starvation in concave pockets.

Each triangle is projected into its own metric 2D frame (t = normalize(B−A), n = normalize((B−A)×(C−A)), b = n×t), so the 2D triangle is congruent to the 3D triangle (true edge lengths/angles, zero distortion, consistent winding). Each triangle’s cell is the axis-aligned bounding box of its projected corners; all cells are packed into the unit square at a single global scale via a binary-searched shelf pack, so texel density tracks 3D area. A per-cell minimum edge (minCellUv) guarantees even tiny triangles receive texels.

Precondition: the input must be fully split (see AutoUV): every triangle owns three unique vertices used by no other triangle. Output shape matches AutoUV.Generate(float3[], int[], float) (one UV per input vertex), so ScatterWedgeUVs and the albedo baker consume it unchanged.

The atlas is deterministic: identical input yields byte-identical UVs across runs.

Methods

static float2[] Generate(
    float3[] vertices,
    int[] indices,
    float padding,
    float minCellUv,
    bool assumeHull = true
)

Generate a per-triangle UV atlas for a fully split triangular mesh.

Parameters:

vertices

Vertex positions. One UV is produced per entry.

indices

Triangle indices (length a multiple of 3), fully split.

padding

Inter-cell gutter, in UV units (also used as the outer border).

minCellUv

Minimum cell edge in UV units (resolution-independent; the caller computes minCellTexels / resolution). Each cell is floored to this size so tiny triangles still get texels. If the floored cells cannot fit the unit square, all cells shrink below the floor uniformly (a warning is logged) rather than overflow or overlap.

assumeHull

When true (default) every non-degenerate triangle gets a cell — trust the caller’s topology. When false the same outward ray-cast AutoUV uses classifies faces, and any triangle judged buried (interior) is excluded (its verts stay at float2.zero). Set it false to keep spurious internal faces (e.g. from a tetrahedralizer that does not weld every shared face) out of the atlas, at the cost of possibly dropping real faces deep in concave pockets.

Returns:

One UV per input vertex; result.Length == vertices.Length.