FlashGenius Logo FlashGenius
NVIDIA NCP-OUSD ยท Exam Weight: ~29%

NCP-OUSD: Data Exchange &
Pipeline Development

The two heaviest combined topic areas on the exam โ€” mastering these skills separates a production USD developer from a student.

60โ€“70 Questions 120 Minutes $200 Exam Fee 2-Year Credential
What This Page Covers
Data Exchange & Pipeline Development

This page covers the two largest combined domain areas of the NCP-OUSD exam: Data Exchange (15%) โ€” writing custom importers/exporters, data mapping, and interchange scripts โ€” and Pipeline Development (14%) โ€” designing studio pipelines, asset management, versioning, USD exporter hooks, build configurations, flattening, and dependency removal. Together they account for roughly 18โ€“20 of your 60โ€“70 questions.

Data Mapping

Conceptual translation between DCC data models (Maya, Houdini, Blender) and USD prims/properties. Mapping tables document the transformation โ€” source type, target prim type, value conversions, axis and unit conventions.

Custom Importers / Exporters

Python scripts using Usd, Sdf, and UsdUtils APIs to bring data into or extract data from USD. Sdf-level authoring is preferred for large bulk imports due to 10โ€“100ร— speed advantage.

USD Exporter Hook

Intercept and transform data as it passes through a DCC's USD export pipeline. Write custom logic to rename prims, remap materials, add metadata, and validate output โ€” all registered via plugInfo.json.

Asset Management & Versioning

Custom ArResolver integrates USD with your studio's asset management system. Version-immutable pipelines create new versions rather than overwriting. Resolvers translate logical identifiers to real file paths.

Core Knowledge
Concepts

Deep-dive on every testable concept in Data Exchange and Pipeline Development, with Python and command-line examples.

Conceptual Data Mapping

Before writing any importer/exporter, create a data mapping document that records:

  • Source system โ€” e.g., Maya DAG, FBX hierarchy, glTF node tree
  • Target USD concept โ€” prim type, path structure, attribute names
  • Value transformations required โ€” axis conversion, unit scaling, naming conventions

Example Mapping Table: Maya โ†’ USD

Source (Maya)Target USD TypeNotes
Transform nodeUsdGeom.XformAxis order, pivot handling
MeshUsdGeom.MeshFace index winding, normals
Shader / MaterialUsdShade.Shader / MaterialParameter mapping per renderer
InstancerUsdGeom.PointInstancer or native USD instancingAmbiguous โ€” document explicitly
CameraUsdGeom.CameraFOV vs aperture conversion

Axis & Unit Conventions

  • Maya = Y-up; USD default = Y-up (Z-up also supported)
  • Specify: stage.SetMetadata("upAxis", "Y")
  • Unit scale: stage.SetMetadata("metersPerUnit", 0.01) for centimeter scenes
  • Ambiguous mappings (e.g., instancing strategy) must be resolved and documented before coding begins

Custom Importers

Pattern: read source data โ†’ create Usd.Stage โ†’ define prim hierarchy โ†’ set attributes โ†’ save

  • Use Sdf.Layer.CreateNew() for efficient batch authoring โ€” bypasses change notification overhead
  • Sdf-level authoring: Sdf.PrimSpec, Sdf.AttributeSpec, Sdf.RelationshipSpec โ€” faster than Usd-level for large imports
  • Validate: UsdUtils.ComplianceChecker for schema compliance; UsdGeom.Imageable for renderable prims
  • Time samples at Sdf level: build a timeSamples dict and set via attr.SetMetadata("timeSamples", {...})
# Sdf-level batch importer (fast)
from pxr import Sdf, Usd, UsdGeom

layer = Sdf.Layer.CreateNew("/tmp/import.usda")
with Sdf.ChangeBlock():
    prim_spec = Sdf.PrimSpec(layer, "MyMesh", Sdf.SpecifierDef, "Mesh")
    prim_spec.SetInfo("kind", "component")
    # Set a points attribute
    attr = Sdf.AttributeSpec(prim_spec, "points", Sdf.ValueTypeNames.Point3fArray)
    attr.SetMetadata("timeSamples", {1.0: [(0,0,0),(1,0,0)], 2.0: [(0,1,0),(1,1,0)]})

layer.Save()
print("Import complete:", layer.identifier)

Custom Exporters

Pattern: traverse Usd.Stage โ†’ convert USD data โ†’ write to target format

  • stage.Traverse() iterates all prims; prim.GetFilteredChildren(predicate) for filtered traversal
  • UsdGeomPrimvarsAPI(prim).GetPrimvars() to collect all primvars
  • Instancing: prim.IsInstance(); get shared data from prim.GetPrototype()
  • Time samples: attr.GetTimeSamplesInInterval(Gf.Interval(startTime, endTime))
  • Flatten before export if needed: stage.Flatten() returns a single-layer Sdf.Layer
from pxr import Usd, UsdGeom, Gf

stage = Usd.Stage.Open("/path/to/scene.usda")

for prim in stage.Traverse():
    if prim.IsA(UsdGeom.Mesh):
        mesh = UsdGeom.Mesh(prim)
        pts_attr = mesh.GetPointsAttr()
        # Export time samples in the shot range
        interval = Gf.Interval(stage.GetStartTimeCode(), stage.GetEndTimeCode())
        time_samples = pts_attr.GetTimeSamplesInInterval(interval)
        print(f"{prim.GetPath()}: {len(time_samples)} time samples")
        # Handle instances
        if prim.IsInstance():
            proto = prim.GetPrototype()
            print(f"  Instance of prototype: {proto.GetPath()}")

USD Exporter Hook

DCC applications (Maya, Houdini) expose a plugin hook that fires during USD export. The hook can:

  • Rename prims to match studio naming conventions
  • Add custom metadata or attributes
  • Remap material paths to the studio's asset library
  • Validate output and raise errors for non-compliant exports

Registration: Maya USD uses mayaUsdTranslatorExport; Houdini uses ROP USD output driver hooks. Both register via plugInfo.json.

// plugInfo.json โ€” registers your export hook plugin
{
    "Plugins": [{
        "Name": "StudioUSDExportHook",
        "Type": "python",
        "Info": {
            "mayaUsdTranslatorExport": {
                "exportParentScope": true
            }
        },
        "LibraryPath": ".",
        "ResourcePath": "."
    }]
}
# studio_export_hook.py โ€” hook implementation
from pxr import Usd, UsdGeom, Sdf

def post_export_callback(stage, export_options):
    """Fired by Maya USD after each prim is exported."""
    for prim in stage.Traverse():
        # Enforce naming convention: all prims lowercase
        if prim.GetName() != prim.GetName().lower():
            stage.GetRootLayer().Rename(
                str(prim.GetPath()),
                str(prim.GetPath()).lower()
            )
        # Stamp with studio metadata
        prim.SetMetadata("customData", {"studio": "MyStudio", "pipeline": "v2"})

Asset Management & Custom Resolvers

  • Default resolver: resolves asset paths relative to the anchoring layer
  • Custom ArResolver: override Ar.Resolver to implement studio-specific path resolution
  • Use case: "asset:myAsset?v=3" resolved to "/studio/assets/myAsset/v003/asset.usda"
  • ArResolver.Resolve(path) โ†’ returns the filesystem path for the given asset identifier
  • Resolver context: ArResolverContext โ€” pass studio session info (shot, sequence, user) to the resolver
  • SearchPath: fallback resolution using a list of root directories
from pxr import Ar

class StudioResolver(Ar.Resolver):
    """Translates 'asset:NAME?v=N' URIs to real file paths."""

    def Resolve(self, path):
        if path.startswith("asset:"):
            name, _, version_str = path[6:].partition("?v=")
            version = int(version_str) if version_str else "latest"
            return f"/studio/assets/{name}/v{version:03d}/asset.usda"
        return super().Resolve(path)

    def CreateDefaultContext(self):
        # Provide shot context from environment
        import os
        return Ar.ResolverContext({"shot": os.environ.get("SHOT", ""), "user": os.environ.get("USER", "")})

Pipeline Design & Asset Versioning

Shot Pipeline Structure

  • /asset/v001/ โ†’ /shot/seq/shot/anim/ โ†’ /shot/seq/shot/lighting/
  • Version immutability: published versions are never edited; new work creates a new version
  • Version pinning: reference "asset?v=3" (resolver handles it) vs hardcoded path
  • Work-in-progress layers: artist edits a "work" layer; publishing bakes it to a versioned path
  • Dependency flattening for delivery: UsdUtils.FlattenLayerStack or stage.Export() bakes all opinions into one layer; removes proprietary references
# Publish a work layer as a new versioned asset
from pxr import Usd, UsdUtils
import shutil, os

work_path = "/studio/work/myAsset/asset.usda"
publish_path = "/studio/assets/myAsset/v004/asset.usda"

# Open work layer and flatten all sublayers
stage = Usd.Stage.Open(work_path)
flat_layer = stage.Flatten(addSourceFileComment=False)

os.makedirs(os.path.dirname(publish_path), exist_ok=True)
flat_layer.Export(publish_path)
print(f"Published to {publish_path}")

Build Configurations & Flattening

  • USD build config: usd_config.cmake or setup.cfg controls which plugins are included
  • Proprietary dependency removal: flatten + strip custom metadata before client delivery
  • stage.Flatten(addSourceFileComment=False) โ†’ one merged layer, no external references
  • UsdUtils.StitchLayers โ€” merge multiple layers into one, preserving time samples
  • usdzip / usdchecker โ€” command-line tools for packaging and validation
# Merge per-frame USD caches into a single multi-frame layer
from pxr import UsdUtils, Sdf

frame_layers = [Sdf.Layer.FindOrOpen(f"/cache/frame.{f:04d}.usd") for f in range(1001, 1049)]
merged = Sdf.Layer.CreateNew("/deliver/animation_cache.usd")
UsdUtils.StitchLayers(merged, frame_layers)
merged.Save()
print("Stitched", len(frame_layers), "frames into animation_cache.usd")
# Command-line: package scene + all dependencies into .usdz
usdzip --asset /path/to/scene.usda /path/to/output.usdz

# Validate before delivery
usdchecker /path/to/output.usdz

# Inspect merged/flat result
usdcat --flatten /path/to/scene.usda
Retention Techniques
Memory Hooks

Six mental shortcuts to anchor the most testable concepts from Data Exchange and Pipeline Development.

"Map First, Code Second"

Always create a data mapping document before writing an importer or exporter. Identify ambiguities โ€” instancing strategy, axis convention, unit scale โ€” before touching Python. Undefined mappings become runtime bugs.

"Sdf-level = Fast Bulk Authoring"

For large imports, use Sdf.PrimSpec / Sdf.AttributeSpec directly โ€” it bypasses USD's change notification system and is 10โ€“100ร— faster than Usd-level authoring via stage.DefinePrim().

"Exporter Hook = Intercept & Transform"

The hook fires during DCC export. Use it to rename, remap, validate, and add metadata โ€” without modifying the DCC scene itself. Registered via plugInfo.json in your plugin directory.

"ArResolver = Asset Path Translator"

Custom resolver maps logical identifiers ("asset:prop?v=2") to real file paths. The ArResolverContext carries shot/user session data so the resolver can make context-aware decisions.

"Flatten = Delivery Mode"

stage.Export() or UsdUtils.FlattenLayerStack() produces a single self-contained layer โ€” remove proprietary paths before handing off to clients or third-party renderers.

"Version Immutability"

Published versions are never edited. Work โ†’ Publish โ†’ New Version. Pipeline tools pin references to specific versions; resolvers handle the path translation. Overwriting published versions corrupts dependent shots.

Test Your Knowledge
Quiz

10 questions on Data Exchange & Pipeline Development. One at a time โ€” choose your answer to advance.

Question 1 of 10 Score: 0

1. What is the primary purpose of a conceptual data mapping document in a USD pipeline?

2. Which USD API layer is fastest for bulk/batch authoring of large scenes during import?

3. What does a USD Exporter Hook allow a developer to do?

4. Which Python call flattens all layers in a stage into a single merged layer?

5. What does a custom ArResolver enable?

6. Which stage metadata attribute specifies the coordinate system orientation?

7. In a version-immutable pipeline, what happens when an artist needs to update a published asset?

8. Which tool packages a USD scene with all dependencies into a single distributable .usdz file?

9. When exporting time-sampled data at the Sdf level, which method efficiently sets all time samples at once?

10. What does UsdUtils.StitchLayers do?

๐ŸŽฏ
Active Recall
Flashcards

Click any card to reveal the answer. Test yourself before reading.

Question

Why use Sdf-level authoring for importers?

Click to flip
Answer

Sdf.PrimSpec / Sdf.AttributeSpec bypass USD's change notification overhead. For importing thousands of prims, Sdf-level is 10โ€“100ร— faster than creating Usd.Prim objects via stage.DefinePrim().

Question

What is a USD Exporter Hook?

Click to flip
Answer

A plugin registered via plugInfo.json that intercepts data during a DCC's USD export. It can rename prims, add metadata, remap paths, and validate output โ€” without modifying the DCC scene.

Question

ArResolver role in the pipeline

Click to flip
Answer

Custom Ar.Resolver subclass that translates logical asset identifiers (studio URNs, version strings) into real file paths. ArResolverContext carries session data (shot, user, environment).

Question

stage.Flatten() vs stage.Export()

Click to flip
Answer

Both produce a single merged layer. stage.Flatten() returns an in-memory Sdf.Layer. stage.Export(path) writes the flattened result directly to a file. Use for delivery to remove all external references.

Question

Data mapping document โ€” what it covers

Click to flip
Answer

Source system data types โ†’ USD prim types, property names, value transformations. Covers: axis convention, unit scale, naming rules, instancing strategy, ambiguous mappings. Written before coding begins.

Question

UsdUtils.StitchLayers

Click to flip
Answer

Merges multiple Sdf.Layer objects into one, correctly combining time samples from all layers. Used for assembling per-frame USD caches into a single multi-frame layer.

Question

Version immutability in pipelines

Click to flip
Answer

Published asset versions are read-only โ€” never overwritten. New work creates a new version number. References/payloads are pinned to specific versions. Resolvers translate version identifiers to paths.

Question

UsdUtils.ComplianceChecker

Click to flip
Answer

Validates a USD stage/layer against USD compliance rules: checks schema correctness, primvar validity, material binding correctness. Use after import to catch authoring errors before publishing.

Exam Strategy
Study Advisor

Targeted guidance for Data Exchange & Pipeline Development โ€” the heaviest combined section of the NCP-OUSD exam.

๐ŸŽฏ Exam Strategy

This is the heaviest combined section (29%). Data Exchange questions test specific API knowledge โ€” Sdf vs Usd level, flatten calls, time-sample methods. Pipeline questions are often conceptual โ€” versioning strategy, resolver role, hook registration. Expect scenario-based questions that describe a pipeline problem and ask which API or design decision solves it.

๐Ÿ“š Core Resources

NVIDIA Learn OpenUSD Module 7 "Developing Data Exchange Pipelines"; USD Pipeline documentation at openusd.org; Ar (Asset Resolution) API docs; plugInfo.json format reference in the USD source. The official NVIDIA certification page links to the OpenUSD Learning Path.

๐Ÿ’ป Hands-On Practice

Write a simple OBJ-to-USD importer using Sdf-level authoring; implement a minimal ArResolver subclass that logs every resolve call; try stage.Flatten() on a multi-sublayer scene and inspect the output in a text editor to see all layers merged.

โš ๏ธ Common Mistakes

Using Usd-level API for large bulk imports (too slow โ€” switch to Sdf); forgetting to set metersPerUnit and upAxis in the exported stage; not handling instancing in exporters (traversal stops at the instance boundary โ€” call prim.GetPrototype() explicitly).

๐Ÿ”— Related Exam Topics

Pipeline Development feeds directly into Customizing USD (6%) โ€” custom schemas and file format plugins are pipeline extension points. Data Exchange knowledge underpins Debugging (11%) because import/export bugs are the most common pipeline failures on production shows.

Official Links
Resources

Authoritative sources for Data Exchange, Pipeline Development, and NCP-OUSD exam registration.

NVIDIA NCP-OUSD Certification Page

Official certification overview, exam objectives, and registration link.

Learn OpenUSD Module 7: Data Exchange Pipelines

NVIDIA's official course module directly covering this exam section โ€” importers, exporters, hooks, and pipeline design.

OpenUSD Asset Resolution (Ar) API Documentation

Complete reference for Ar.Resolver, ArResolverContext, and the full asset resolution framework.

UsdUtils API Reference

Documents UsdUtils.FlattenLayerStack, UsdUtils.StitchLayers, UsdUtils.ComplianceChecker, and packaging utilities.

Register for the NCP-OUSD Exam

Schedule and purchase your NCP-OUSD exam via Certiverse (NVIDIA's official exam delivery partner). $200 exam fee.

NCP-OUSD Exam
Ready to earn your NVIDIA OpenUSD credential?
60โ€“70 questions ยท 120 minutes ยท $200 ยท 2-year credential ยท Intermediate level