mesh

A general indexed triangle-mesh Mob.

Unlike Surface (which is parametric – a coord_function sampled on a regular UV grid), TriangleMesh renders an arbitrary triangle soup: explicit per-corner positions, normals and UVs plus an optional texture map. This is the geometry container that Model3D builds each imported mesh node from, but it is usable on its own for any hand-built or procedurally generated mesh.

The class mirrors Surface’s render structure exactly – a parent Mob holding a child self.grid Mob that carries the per-corner geometry as its animatable location/color – so it plugs into the same scene materialization, batching and (ray traced) texture pipeline that already drives Surface/ImageMob. Storing the corners as an animatable attribute is also what lets a later animation phase drive per-frame vertex positions (skinning / morph baking) with no renderer changes: the spatio-temporal BVH already consumes [T, N, 3, 3] corners.

Classes

TriangleMesh

An arbitrary indexed triangle mesh with optional per-corner normals, UVs and a texture map.

Functions

image_to_normal_map(image, flip_green=True)[source]

Convert a tangent-space normal map image [H, W, 3] in [0, 1] (rgb-encoded, n = 2*rgb - 1) to the [W, H, 3] layout the ray tracer samples, with components in [-1, 1] (x along +u, y along +v, z along the smooth normal).

Uses the same spatial transform as image_to_texture_map() so the map aligns with the (v-flipped) UVs. Because that v-flip reverses the tangent’s v direction, the map’s green (y) channel is flipped by default so a glTF (+Y / OpenGL) normal map lights correctly; set flip_green=False for already-agreeing (DirectX-style) maps.

image_to_texture_map(image)[source]

Convert an image [H, W, C] (rows top-to-bottom, C in 1/3/4 channels) to the [W, H, 5] texture-map layout the ray tracer samples, matching the convention used by ImageMob.

The kernel indexes a texture by u along the first stored axis and v along the second (local_idx = u_idx * height + v_idx, see _sample_texture in ray_trace_taichi), with v measured bottom-up. An image is stored [row, col] with row top-down, so we transpose [H, W] -> [W, H] (columns become the u axis) and flip the v axis. Channels are padded to the engine’s 5-slot color (r, g, b, glow, opacity) by Color.add_defaults.