一键导入
create-proxy
Create a USD proxy mesh sibling. Use to generate decimated, bbox, or LOD stand-ins, with optional render/proxy purpose variant set.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Create a USD proxy mesh sibling. Use to generate decimated, bbox, or LOD stand-ins, with optional render/proxy purpose variant set.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | create-proxy |
| description | Create a USD proxy mesh sibling. Use to generate decimated, bbox, or LOD stand-ins, with optional render/proxy purpose variant set. |
| version | 1.0.0 |
| allowed-tools | Read, Write, Bash |
| metadata | {"author":"NVIDIA Corporation","tags":["usd","proxy","lod","decimation"]} |
Generate a low-detail proxy mesh as a sibling of a source prim hierarchy, then mark the two with USD purpose so downstream tooling can pick render vs. proxy automatically. The result is roughly:
/World/Asset ← source (untouched), purpose = render
/World/Asset_proxy ← merged + decimated mesh, purpose = proxy
Use this skill when a user asks to:
purposeThis SKILL.md is the navigation layer. Detailed step bodies live in references/ so the agent can fetch them on demand. Search for keywords like decimate, bbox, variant, pre-flight, pitfalls, verification to jump.
Companion: operation guides under .agents/operations/ for each underlying operation.
This skill has two operating modes — pick based on what the user asked for:
Operating rules for either mode:
pythonScript script bodies belong in an agent-writable scratch directory the user has approved — typically the OS temp dir, but if you're sandboxed (Codex, etc.) use whichever writable root the runtime allows. Don't drop scratch files in docs/, source/, usd-optimize/source/, or any version-controlled location. Save in-tree only when the user explicitly asks.<base64 ...> placeholders. The example assembled config in references/decimate-mode.md and references/bounding-box-modes.md shows shape, not a runnable artifact. Encode each script body before invoking the runner, and omit disabled optional steps entirely (drop Step 2 when stripAnimation: false, drop Step 6 when setupVariantSet: false) — don't ship empty/placeholder bodies.The user must supply sourcePrimPath. Everything else has a default:
| Input | Default | Meaning |
|---|---|---|
sourcePrimPath | (required) | Absolute path of the source prim, e.g. /World/Asset. |
proxyMode | "decimate" | Which proxy strategy: "decimate" (merge + decimate the source — full pipeline, recognizable shape), "boundingBoxWhole" (single 8-vert AABB around the source — cheapest possible proxy), or "boundingBoxPerMesh" (one AABB per leaf mesh, mirroring source hierarchy — preserves silhouette). See Choosing your proxy mode below. |
reductionFactor | 25.0 | (Decimate mode only.) decimateMeshes target percentage of vertices to retain (0–100). 25 = keep 25%. Set to 0.0 if maxMeanError should drive stopping. |
maxMeanError | 0.0 | (Decimate mode only.) decimateMeshes max mean geometric error. 0.0 = disabled. |
stripAnimation | true | (Decimate mode only.) Strip time samples on the proxy subtree before merging. Bounding-box modes don't copy source data so this doesn't apply. |
setupVariantSet | false | Author a variant set that flips render/proxy purposes. When true, the four overrides below kick in. |
variantSetParentPath | parent of source | Prim where the variant set is authored. Must be an ancestor of both sourcePrimPath and the proxy. |
variantSetName | "displayPurpose" | Name of the variant set. |
defaultVariantName | "render" | Default variant: source.purpose=render, proxy.purpose=proxy. |
swappedVariantName | "proxy" | Swapped variant: source.purpose=proxy, proxy.purpose=render. |
The proxy path is always <sourcePrimPath>_proxy — derived from the source path, not user-configurable.
Three modes; pick by use case, not by what looks visually nice:
| Mode | Output | Cost | When to use |
|---|---|---|---|
decimate | Reduced-poly version of the merged source. | Topology-floor surprises; iterate-with-user loop. | Default. Proxy should "look like" the source at distance — recognizable shape with a smaller poly count. |
boundingBoxWhole | Single 8-vert AABB around the entire source. | Constant 8 verts. Fully deterministic. | Occluder, picking proxy, far-far LOD where shape recognition is irrelevant. Cheapest possible representation. |
boundingBoxPerMesh | One AABB per leaf mesh, mirroring source hierarchy. | 8 × source_mesh_count verts. Fully deterministic. | Silhouette/structure preservation as a "Lego" approximation. Recognizable preview without paying for decimation. |
The bbox modes don't iterate — output is fully determined by the source's AABB(s). The matrix and the iterate-with-user loop only apply to decimate mode (see references/parameter-tuning.md).
| To do this... | You need... |
|---|---|
| Generate the JSON config | sourcePrimPath. Everything else has a default. |
| Execute the config | The above, plus: input USD path, output USD path, and a Usd Optimize runtime — either a source-tree build or an installed prebuilt package. |
For runtime setup, defer to the existing skills rather than duplicating instructions here:
.agents/skills/build/SKILL.md..agents/skills/prebuilt-package/SKILL.md.When proxyMode: "decimate":
<sourcePrimPath>_proxy (pythonScript).pythonScript).merge).decimateMeshes with allowCutAndGlue: true).pythonScript).pythonScript).When proxyMode: "boundingBoxWhole" or "boundingBoxPerMesh":
pythonScript (replaces Steps 1–4 above): defines <source>_proxy as a fresh Xform and authors one or more AABB box meshes inside it.Steps 1, 2, 5, 6 (decimate mode) and the bbox-authoring step are USD authoring glue not covered by Usd Optimize ops; they run via the pythonScript operation. Steps 3, 4 (decimate mode only) are native Usd Optimize operations.
Validate these before invoking the pipeline — they aren't gated by the operations themselves, so running blind on a missing prim or empty subtree produces a confusing failure deep into the run.
sourcePrimPath resolves on the input stage. Open the file (e.g. via usdview or a quick pxr.Usd.Stage.Open + GetPrimAtPath) and confirm the prim exists. Step 1 raises if it doesn't.UsdGeomMesh. If it's only Xforms or non-mesh prims, Step 3 (merge) has nothing to consolidate and Step 4 will decimate nothing. Worth a quick traversal:
from pxr import Usd, UsdGeom
src = stage.GetPrimAtPath("/World/Asset")
has_mesh = any(p.IsA(UsdGeom.Mesh) for p in Usd.PrimRange(src))
<sourcePrimPath>_proxy does not already exist. If it does, decide with the user before proceeding:
Sdf.CopySpec overwrites authored specs at that path on the edit-target layer.pythonScript step that calls stage.RemovePrim("<source>_proxy") (or use the removePrims operation).<source>_proxy in every step; a different suffix means editing the steps consistently.Sdf.CopySpec copies only the authored specs at the current edit-target layer — it does NOT copy the fully composed prim. Two failure modes:
usdview. Verify by checking stage.GetEditTarget().GetLayer().GetPrimAtPath(SOURCE_PATH) — if that returns None or a spec with no children, copy will not produce a usable proxy.The detailed step bodies, parameter tables, and end-to-end runner code live in companion docs to keep this SKILL.md focused on routing decisions:
| Reference | Covers |
|---|---|
references/decimate-mode.md | Steps 1–6 for decimate mode (deep copy, strip animation, merge, decimate with Topology Simplification, set purposes, optional variant set), the assembled JSON config, and the standalone end-to-end runner. |
references/bounding-box-modes.md | Common scaffolding + Mode A (boundingBoxWhole) + Mode B (boundingBoxPerMesh), plus the assembled JSON config for bbox mode. |
references/parameter-tuning.md | reductionFactor vs maxMeanError, the vertex-count starting-value matrix, agent-side pre-analysis script, runtime verification, and the iterate-with-user loop. |
<sourcePrimPath> resolves to only Xforms or non-mesh prims, merge has nothing to consolidate. Validate before running, or expect an empty proxy.utilityFunction with function: "Deinstance" on the proxy subtree between Step 1 and Step 2.Sdf.CopySpec copies the spec at the edit target. The proxy will resolve the same composition arcs as the source (referenced/payloaded layers continue to resolve from their original locations). For a fully self-contained proxy, flatten references first.attr.Set(first_value) authors a default at the edit target, and that default wins over any time samples in deeper layers. The proxy reads static at first-sample value. The override only holds while the edit target is stronger than the layer carrying the animation. For full safety in those setups, flatten the source's composition arcs before running this skill.attr.GetNumTimeSamples() is value-resolved across all layers, so after the strip it can still report samples from a referenced layer. Verify with attr.Get(some_time) if you need to confirm the stronger default authored by the strip is what downstream consumers see.merge bakes local transforms into vertex positions. After Step 3 the merged mesh sits at <source>_proxy with identity transform.variantSetParentPath must be an ancestor of both <source> and <source>_proxy. The default (parent of source) satisfies this for sibling layout. Setting it elsewhere produces a variant that cannot reach the prims it is meant to swap.allowCutAndGlue: true is slower than the default decimator path. For very large stages, expect Step 4 to dominate runtime.After the pipeline runs, confirm:
<sourcePrimPath>_proxy exists and contains a single UsdGeomMesh (or one per material bucket if considerMaterials: true).purpose == render, proxy purpose == proxy:
print(UsdGeom.Imageable(stage.GetPrimAtPath("/World/Asset")).GetPurposeAttr().Get())
print(UsdGeom.Imageable(stage.GetPrimAtPath("/World/Asset_proxy")).GetPurposeAttr().Get())
reductionFactor% of the merged-but-not-yet-decimated count. Use printStats (analysis mode) before and after Step 4 for a quick sanity check.setupVariantSet: true: list variants on the parent prim and toggle them; the two purposes should flip between variants.Generate a low-detail proxy sibling for a high-resolution USD subtree
and tag the two prims with USD purpose so DCCs and renderers can
pick render vs. proxy automatically. Supports three strategies —
decimate (merge + Topology Simplification), bounding-box-whole, and
bounding-box-per-mesh — plus an optional variant set that flips the
purpose pair on demand.
sourcePrimPath containing at least
one UsdGeomMesh (decimate / boundingBoxPerMesh modes); for
boundingBoxWhole only the source bounding box is needed.build skill or an installed prebuilt-package), an input USD
path, and an output USD path.sourcePrimPath and the desired
parameters. The output is the assembled JSON config.pythonScript bodies and the assembled config.purpose and an
optional variant set; it does not configure how a specific renderer
(Hydra, Storm, RTX, Maya, Houdini, …) presents them.allowCutAndGlue: true) is slow on very
large stages. Decimate runtime can dominate the pipeline; the
iterate-with-user loop assumes the user can wait.| Symptom | Likely cause | Fix |
|---|---|---|
| Proxy is empty after the run | Source has no authored spec at the edit-target layer (reference/payload only). | Flatten the source subtree first, or set the edit target to a layer that carries the source's specs. |
| Proxy has many small meshes despite Step 3 | Default mergePoint: 1 skips boundaries with a single mesh. | Set allowSingleMeshes: true, or widen with mergePoint: 7 (Root Prim) / 0 (Stage). See references/decimate-mode.md § Step 3 variants. |
| Decimation overshoots the target % | Topology floor — many small meshes can't shrink below their minimum vertex count. | Drop reductionFactor further (e.g. 5 → 1) or accept the floor; see references/parameter-tuning.md § What to expect from the actual numbers. |
| Bbox box renders as a rounded blob | Default Catmull-Clark subdivision applied. | Ensure subdivisionScheme = "none" and faceVarying normals are authored — both are in references/bounding-box-modes.md § Common scaffolding. |
purpose doesn't flow to descendants | Some descendant has its own authored purpose opinion. | Use _set_purpose_subtree in references/decimate-mode.md § Step 5 (it clears descendant authored opinions). |
| Variant body errors with "can't author opinion" | variantSetParentPath is not an ancestor of both source and proxy. | Pick a common ancestor (default: parent of source). |
pythonScript step fails JSON parse | A <base64 ...> placeholder was left in the assembled config. | Replace every placeholder with the actual base64-encoded body before running. |
Reference for Usd Optimize's validator infrastructure (registration, CLI, logging, REQUIRES_MESH cache). Do not use for ad-hoc validation runs — use run-validators instead.
Build Usd Optimize from source via repo.sh (Linux) or repo.bat (Windows). Use when compiling the repo, switching configs, or selecting a USD flavor.
Diff two USD stages by prim/mesh/vertex/material count, file size, and validator summary. Use for before/after optimization comparisons.
Triage a failing Usd Optimize operation. Use when an op errors, silently no-ops, or returns unexpected output.
Collapse duplicate prim hierarchies into instanceable internal references. Use when deduplicating subtrees or folding repeated prims into prototypes.
Read saved validator artifacts and present a tier-classified report with per-rule prim lists and fix recommendations. Use when interpreting a saved run.