Skip to content

Mesh Painting & Sculpting

The various 3D painting modes (Sculpt, Vertex Paint, Weight Paint) all share similar concepts for both rendering and processing of data.

Storage Backends

Data in Sculpt mode is ultimately stored in one of three areas depending on the rough "mode" being used.

Mesh

The default source of data for Sculpt mode if neither of the two other modes are applicable. See here for more information.

BMesh

Used when Dyntopo is active. See here for more information. Note that this data is runtime only and not persisted to file.

Grids

Used when the Multiresolution modifier is active. The SubdivCCG struct is used to store object space positions and normals, which is then stored as a CustomData layer in tangent space when sculpt mode is exited.

Paint BVH

The Paint BVH is an acceleration data structure for allowing raycasts, coarse filtering, and selective GPU updates. As a mesh increases in number of vertices, the BVH is split into more nodes. Currently, data is partitioned based on vertex position and corresponding material index. Each BVH node is used to partition draw calls for the GPU.

Brush Strokes

For most mesh brushes, to calculate the effect that it has within the displayed brush radius, we calculate the relative influence that a stroke step has on a given vertex based on brush parameters, distance to the center of the cursor, and existing mesh values.

Runtime Structures

There exist a number of structs that only live at runtime of the application and are not persisted between Blender closing and opening.

For all the painting modes, some data lives in the SculptSession struct which is cleared only when switching between modes.

Only data that should last longer than a particular brush stroke should live in SculptSession - for example, data needed to preview a given brush, undo information for BMesh, the currently active vertex, etc

Other data specific to a stroke lives inside StrokeCache and in derived classes of PaintModeData. These are expected to only live within the context of a single stroke.

This stroke specific data generally falls into the following categories:

  • Cached operator data, usually parameters that may change based on user input, but not over the course of a stroke.
    • Examples: Smooth or alt brush modes
  • Cached brush data and a limited set of variables that may change over the course of a brush.
    • Examples: Radius, calculated brush strength, inverse matrices, pressure, etc
  • Temporary stroke data needed for calculating effects, stored as single values.
    • Examples: Current or previous positions, normals, deltas
  • Temporary mesh-level attributes used for calculating effects, stored as large arrays.
    • Examples: Pose and Boundary brush data