# Subpart Material

> SubpartMaterials are components that contain materials applied to a Part component, it provides a direct and intuitive way to control materials on subparts. This allows assigning materials on individual submesh, giving users precise control over visual appearance.

This component is also useful for **customizing materials on instances**:  Each instance of a prototype can have its own `SubpartMaterial` component.

#### Accessing Subpart Materials

* [scene.listSubpartmaterials](/asset-transformer-sdk/2026.4/api/python/scene_functions.md#listsubpartmaterials)
* [scene.getSubpartmaterial](/asset-transformer-sdk/2026.4/api/python/scene_functions.md#getsubpartmaterial)

#### Setting Subpart Materials

* [scene.setSubpartMaterials](/asset-transformer-sdk/2026.4/api/python/scene_functions.md#setsubpartmaterials)
* [scene.setSubpartMaterial](/asset-transformer-sdk/2026.4/api/python/scene_functions.md#setsubpartmaterial)

> **Important:**
>
> The number of subpart materials in a `SubpartMaterial` component must exactly match the number of submeshes in the associated part.

> **Important:**
>
> In the UI, it is also possible to apply a subpart material to the submeshes via the “+” tab in the **Occurrence Inspector**.

### Material Priority / Override Hierarchy

The material system follows a clear priority hierarchy, where higher levels override the ones below:

1. **Subpart Material** *(Highest Priority)*\
   Assigned directly to a subpart using code (`setSubpartMaterial`). This takes precedence over all other material assignments.

2. **Occurrence Material**\
   Applied to a specific occurrence in the scene.

3. **Inherited Material**
   If no material is set at the above levels, a material can be inherited from a parent node or structure in the scene tree.

4. **Submesh Material**  *(Lowest Priority)*\
   The default material assigned to the submeshs(patches) during import or modeling. However, this is a legacy method and will be deprecated in future versions.

## Example

### Python Example: Assigning Materials to Subparts

Below are two python examples demonstrating how to assign materials to subparts using the SubpartMaterial component. The first applies materials directly on a cube. The second shows how to assign different subpart materials per instance using a shared prototype.

#### Apply on subparts

```python
# Define a list of RGBA colors
colors = [
    [1.0, 0.0, 0.0, 1.0],  # Red
    [0.0, 1.0, 0.0, 1.0],  # Green
    [0.0, 0.0, 1.0, 1.0],  # Blue
    [1.0, 1.0, 0.0, 1.0],  # Yellow
    [0.0, 1.0, 1.0, 1.0],  # Cyan
    [1.0, 0.0, 1.0, 1.0],  # Magenta
]

# Create a cube of dimensions 100x100x100
cube = pxz.scene.createCube(100, 100, 100)

# Set the cube's parent to the root node in the scene
pxz.scene.setParent(cube, pxz.scene.getRoot())

# Automatically identify patches (subparts) for material assignment. `identifyPatches` detects 6 planar faces on the cube, resulting in 6 submeshes (subparts).
pxz.algo.identifyPatches([cube])

# Assign a different material/color to each subpart of the cube
for i in range(6):
    mat = pxz.material.createMaterial(f"mat{i}", "color")
    pxz.material.setMaterialMainColor(mat, colors[i])
    pxz.scene.setSubpartMaterial(cube, i, mat)
```

> **Tip:**
>
> `algo.identifyPatches` is used to generate submeshes when geometry lacks them.

#### Apply on instances

```python
# Define a list of colors for subpart materials
colors = [
    [1.0, 0.0, 0.0, 1.0],  # Red
    [0.0, 1.0, 0.0, 1.0],  # Green
    [0.0, 0.0, 1.0, 1.0],  # Blue
]

# Create a base cube (shared geometry for all instances)
cube = pxz.scene.createCube(100, 100, 100)

# Assign a default gray material to the prototype (occurrence level)
default_mat = pxz.material.createMaterial("default_mat", "color")
pxz.material.setMaterialMainColor(default_mat, [0.5, 0.5, 0.5, 1.0])  # Gray
pxz.scene.setOccurrenceMaterial(cube, default_mat)

# Create three instances and assign materials
for i in range(3):
    # Create a new occurrence and attach it to the scene
    inst = pxz.scene.createOccurrence(f"instance{i+1}")
    pxz.scene.setPrototype(inst, cube)
    pxz.scene.setParent(inst, pxz.scene.getRoot())

    # Offset each instance in X (skip the first one)
    if i > 0:
        matrix = pxz.scene.getLocalMatrix(inst)
        matrix[0][3] += i * 150
        pxz.scene.setLocalMatrix(inst, matrix)

    # Create and assign a unique material to subpart 0 of each instance
    mat = pxz.material.createMaterial(f"mat{i+1}", "color")
    pxz.material.setMaterialMainColor(mat, colors[i])
    pxz.scene.setSubpartMaterial(inst, 0, mat)
```

### File Format Support

The following file formats support Import and/or Export of `subpartMaterial` components:

| 3D Format | Import          | Export      |
| --------- | --------------- | ----------- |
| GLTF/GLB  | ❌ Not supported | ✅ Supported |
| JT        | ❌ Not supported | ✅ Supported |
| DAE       | ❌ Not supported | ✅ Supported |
| USD       | ❌ Not supported | ✅ Supported |
| FBX       | ❌ Not supported | ✅ Supported |
| OBJ       | ❌ Not supported | ✅ Supported |
| PDF       | ❌ Not supported | ✅ Supported |
| PRC       | ❌ Not supported | ✅ Supported |
| PXZ       | ❌ Not supported | ✅ Supported |
| 3DXML     | ❌ Not supported | ✅ Supported |

> **Important:**
>
> ❌ **Not supported**  does not mean we do not import materials on submeshes. In many cases, materials assigned directly to submeshes are preserved. What's missing is the ability to preserve per-instance overrides — for example, if different instances of the same geomatry have different materials on the same submeshes.
