newton.utils.MeshAdjacency#

class newton.utils.MeshAdjacency(tri_indices=None, edge_indices=None, spring_indices=None, tet_indices=None, indices=None)[source]#

Bases: object

Connectivity tables of a soft (triangle) mesh, consumed by collision and the solvers.

Three kinds of topology are stored, all derived from a triangle mesh and its bending edges. The edge/triangle tables are dense arrays indexed by element and are computed eagerly in the constructor (independent of the vertex count). The vertex-adjacency CSR tables are built on demand by init_vertex_adjacency() (which needs only the particle count – the element topology is stored on the object). Every table is a host NumPy array; to() copies the vertex-adjacency CSR into a MeshAdjacencyData struct for use inside Warp kernels.

Obtain an instance by construction — MeshAdjacency(tri_indices) — or from a finalized model via newton.Model.soft_mesh_adjacency.

edge_indices#

Undirected edges as [o0, o1, v0, v1] rows, int32 shape [edge_count, 4]: the edge connects v0-v1, and o0/o1 are the opposite vertices of its two adjacent triangles (o1 == -1 on a boundary edge).

edge_tri_indices#

The two triangles sharing each edge as [f0, f1] rows, int32 shape [edge_count, 2] (f1 == -1 on a boundary edge); f0 is the triangle whose opposite vertex is o0.

tri_edge_indices#

Each triangle’s three edges, int32 shape [tri_count, 3]; column k is the edge between the triangle’s local vertices k and (k + 1) % 3, or -1 if that edge was never registered (e.g. a bare triangle).

v_adj_edges, v_adj_tris, v_adj_springs, v_adj_tets

Per-vertex CSR adjacency to bending edges / triangles / springs / tetrahedra, each paired with its matching *_offsets. *_offsets is int32 of length particle_count + 1, and vertex i’s records occupy v_adj_X[offsets[i] : offsets[i + 1]]; a record is an (element_id, local_slot) pair (a single element_id for springs). All eight arrays are None until init_vertex_adjacency() runs.

vertex_adjacency_initialized#

Whether the vertex-adjacency CSR has been built; init_vertex_adjacency() returns early when this is already True.

indices, spring_indices, tet_indices

The triangle / spring / tetrahedron topology this adjacency is built over, kept from the constructor for init_vertex_adjacency().

Note

The edges dict is a deprecated compatibility shim (it emits a DeprecationWarning); use the edge_indices / edge_tri_indices arrays instead.

class Edge(v0, v1, o0, o1, f0, f1)#

Bases: object

Legacy per-edge record: edge (v0, v1) with opposite vertices o0/o1 and adjacent triangles f0/f1 (-1 if boundary).

__init__(v0, v1, o0, o1, f0, f1)#
f0: int#
f1: int#
o0: int#
o1: int#
v0: int#
v1: int#
static compute_vertex_adjacency(particle_count, *, edge_indices=None, tri_indices=None, spring_indices=None, tet_indices=None)#

Build a temporary adjacency over the given elements and its vertex-to-element CSR.

__init__(tri_indices=None, edge_indices=None, spring_indices=None, tet_indices=None, indices=None)#

Build edge adjacency from triangles and store the element topology as members.

Parameters:
  • tri_indices (Sequence[Sequence[int]] | ndarray | None) – Triangle indices, shape [tri_count, 3], used to derive the edge/triangle maps. None leaves the edge tables empty.

  • edge_indices (Sequence[Sequence[int]] | ndarray | None) – Pre-numbered bending edges, shape [edge_count, 4] as [o0, o1, v0, v1]. When given, this exact edge numbering is kept (so it stays aligned with externally stored bending materials) and only the edge/triangle maps are derived against tri_indices. When None, edge_indices is computed from tri_indices.

  • spring_indices (Sequence[int] | ndarray | None) – Spring endpoint pairs, flat shape [2 * spring_count]; stored for init_vertex_adjacency().

  • tet_indices (Sequence[Sequence[int]] | ndarray | None) – Tetrahedron vertex ids, shape [tet_count, 4]; stored for init_vertex_adjacency().

  • indices (Sequence[Sequence[int]] | ndarray | None) – Deprecated alias for tri_indices.

add_edge(i0, i1, o, f)#

Add or update one edge (deprecated; build via edge_indices instead).

Legacy incremental API: edge (i0, i1) with opposite vertex o in triangle f. The first call for an edge fills o0/f0, the second fills o1/f1; a third warns (non-manifold). Updates edge_indices / edge_tri_indices (so edges reflects it) and invalidates the vertex-adjacency CSR. It does not update tri_edge_indices, so an edge added this way will not appear in the per-triangle edge map; users can reconstruct via the constructor if they need that. O(edge_count) per call – a compatibility shim, not a hot path.

Parameters:
  • i0 (int) – First edge endpoint.

  • i1 (int) – Second edge endpoint.

  • o (int) – Opposite vertex in triangle f.

  • f (int) – Triangle containing this edge.

init_vertex_adjacency(particle_count)#

Compute and store the vertex-to-element CSR tables from the stored topology.

Builds per-vertex adjacency to the bending edges, triangles, springs and tetrahedra held on this object (edge_indices, indices, spring_indices, tet_indices). Idempotent: returns early once built. The count/fill Warp kernels run on the host; to() later uploads the result to a device.

Parameters:

particle_count (int) – Number of particles; sizes the per-vertex CSR offsets.

to(device)#

Upload the device-facing adjacency arrays onto device as a pure data struct.

Always uploads the edge/triangle topology maps. The vertex-adjacency CSR is uploaded only when init_vertex_adjacency() has populated it; otherwise the eight v_adj_* fields are left None and a warning is emitted (the struct is still usable for callers that only need the topology maps). This is the only place the host NumPy tables become Warp arrays.

property edges: dict[tuple[int, int], Edge]#

Deprecated legacy edge dict, rebuilt on access from edge_indices.

Maps (min(v0, v1), max(v0, v1)) to an Edge. Recomputed on every access and never cached; prefer the edge_indices / edge_tri_indices arrays directly.