AEGLOSLAB 엔비디아 기술 스택

제10부 시뮬레이션·디지털트윈·피지컬 AI

10.3 OpenUSD I — Stage·Prim·Layer

10.3.1 이 장에서 배우는 것 / 선수 지식

9.11~10.2에서 Isaac Sim·Omniverse의 모든 것 — 씬·협업(Nucleus)·렌더(RTX)·연결(커넥터) — 이 USD 위에 선다고 반복했다. "USD가 접착제"라고만 하고 미뤘던 그 USD 자체의 데이터 모델을 이제 판다. OpenUSD(Universal Scene Description) 는 픽사가 만든 3D 씬을 기술하고 구성하는 오픈 표준이고, 그 핵심 자료구조가 Stage(합성된 씬)·Prim(객체 노드)·Layer(저장·합성 단위) 다. 이 셋을 이해하면 "왜 Omniverse·로봇 시뮬·디지털트윈이 USD 위에 서는가"가 데이터 모델 차원에서 보인다. 컴포지션의 깊은 메커니즘(참조·변형·상속 등)은 10.4.

핵심 통찰: USD는 "파일 포맷"이 아니라 "비파괴적 합성(non-destructive composition)을 위한 씬 데이터베이스"다. USD의 실질적 힘은 메시·라이트를 담는 것이 아니라, 여러 레이어(layer)의 "의견(opinion)"을 비파괴적으로 겹쳐 하나의 씬(Stage)으로 합성하는 데 있다. 베이스 씬은 건드리지 않고 더 강한 레이어에서 덮어쓰기(override)만 한다 — 그래서 여럿이 같은 씬을 동시에 편집해도(Nucleus 협업 10.2) 서로의 작업을 안 깨고, 도메인 랜덤화(9.14)가 베이스를 보존한 채 변형을 오버레이하고, 디지털트윈이 설계 위에 운영 데이터를 겹친다. Stage는 결과(합성된 씬), Layer는 재료(의견의 묶음), Prim은 그 안의 객체. 이 분리가 USD가 협업·시뮬·트윈의 토대가 된 이유다.

배우는 것:

  • OpenUSD란 — 씬을 기술·구성하는 오픈 표준(픽사·AOUSD), 왜 Omniverse·로봇이 그 위에.
  • Stage — 레이어들을 합성한 결과인 씬그래프(작업·질의·편집 대상).
  • Prim — 씬의 노드(경로·타입(스키마)·계층) — 메시·라이트·Xform·로봇.
  • 속성 — Attribute(타입 있는 값·타임샘플=애니메이션)·Relationship(다른 프림 가리킴).
  • Layer — 저장·합성의 단위, 오피니언·비파괴 오버라이드·.usda/.usdc. 협업(10.2)·랜덤화(9.14)의 근거.

선수 지식: 10.1·10.2(Omniverse·Nucleus — USD가 그 토대)·9.11(USD 씬·아티큘레이션)·9.14(도메인 랜덤화 — 레이어 오버라이드). 컴포지션 아크(참조·페이로드·변형·상속·특수화·서브레이어 — LIVRPS)의 심화는 10.4, 합성데이터는 10.5, 디지털트윈은 10.8. 씬그래프·계층 구조 개념은 가정(BK-02).

정직: USD는 픽사 발 오픈소스·오픈 표준(AOUSD — NVIDIA·픽사·어도비·애플·오토데스크 등) 으로, NVIDIA 전유물이 아니다(여러 도구가 USD 지원, 10.2). API(pxr.Usd·UsdGeom 등)는 비교적 안정적이나 버전·스키마 확장은 의존이 있다. 이 장은 "USD 데이터 모델의 구조·원리(Stage/Prim/Layer·비파괴 합성)"를 가르치고, 구체 스키마·API·확장은 "그 버전 USD 문서로 확인". 코드(.usda·pxr)는 개념 골격이되 USD API는 실제와 가깝게 둔다. 컴포지션의 강도 규칙(LIVRPS) 등 깊은 부분은 10.4로 미룬다.

10.3.2 OpenUSD란 — 씬을 기술·구성하는 오픈 표준

OpenUSD는 단순한 3D 파일 포맷(FBX·OBJ 같은)이 아니라 씬을 기술(describe)하고 구성(compose)하는 시스템이다.

   USD가 다른 포맷과 다른 점:

   전통 포맷(FBX·OBJ·glTF): "씬 하나를 한 파일에 일괄 직렬화"
     · 하나의 묶음, 편집은 파괴적(원본 수정), 협업·재사용·오버라이드 어려움

   USD: "여러 레이어의 의견을 비파괴적으로 합성해 씬을 만든다"
     · 씬 = 레이어들의 합성 결과(Stage)
     · 베이스는 그대로, 더 강한 레이어에서 덮어쓰기(override)
     · 참조(reference)로 자산 재사용, 변형(variant)으로 옵션(10.4)
     · 대규모·협업·비파괴·상호운용

   왜 픽사가 만들었나: 영화 한 씬에 수백 아티스트·수만 자산이
     동시에·비파괴적으로·재사용하며 작업해야 → 합성 시스템이 필요
  • 합성(composition) 시스템: USD의 본질은 여러 출처(레이어)의 씬 기술을 규칙대로 합쳐 하나의 씬을 만드는 것. 이것이 "기술 + 구성"이고, 단순 포맷과의 결정적 차이(심화 10.4).
  • 비파괴(non-destructive): 자산·베이스 씬을 수정하지 않고 다른 레이어에서 변경을 오버레이한다 — 영화에서 라이팅 팀이 모델 팀의 자산을 안 건드리고 조명만 바꾸듯. 협업·재사용·실험의 핵심.
  • 왜 Omniverse·로봇이 USD 위에(10.1·10.2): ① 협업(Nucleus) — 여럿이 비파괴적으로 동시 편집 ② 상호운용 — 도구 간 공통 언어(커넥터 10.2) ③ 재사용·스케일 — 자산 참조·대규모 씬 ④ 시뮬·트윈 — 같은 씬을 설계·시뮬·운영이 공유. 이 모두가 USD의 합성 모델 덕.
  • 오픈 표준(정직): USD는 픽사 발 오픈소스이고 AOUSD(Alliance for OpenUSD) 로 표준화(NVIDIA·픽사·어도비·애플·오토데스크 등) — NVIDIA 고유가 아니라 업계 공통. Omniverse는 USD를 잘 구현·확장한 플랫폼일 뿐(10.2).

핵심: USD는 파일 포맷이 아니라 씬을 기술·합성하는 시스템이다 — 여러 레이어의 의견을 비파괴적으로 합성해 씬을 만든다(베이스 보존·오버라이드·재사용). 픽사가 대규모 협업 영화 제작을 위해 만들었고, 그 합성 모델이 Omniverse·로봇 시뮬·트윈(10.1·10.2·10.8)의 토대. 오픈 표준(AOUSD) — NVIDIA 전유물 아님.

10.3.3 Stage — 합성된 씬

Stage(스테이지) 는 USD에서 작업하는 씬 — 여러 레이어를 합성한 결과인 씬그래프다.

레이어들 (재료) Stage(결과) — 씬그래프 합성 override.usda (강) /World/Cube 색 변경 base.usda (약) /World/Cube, / Sun /World Cube (베이스 + 색 오버라이드 적용) Sun ...

Stage는 '최종 합성된 뷰'로 우리가 질의·편집·렌더하는 대상이다. 같은 레이어를 합성하면 같은 Stage(재현)이고, Stage를 통해 Prim을 순회·읽기·쓰기한다(쓰면 특정 레이어에 기록).

  • Stage = 결과, Layer = 재료: Stage는 직접 저장되는 것이 아니라, 레이어들을 합성한 런타임 뷰다. 레이어(파일)를 열어 합성하면 Stage가 생긴다 — Usd.Stage.Open("root.usda").
  • 씬그래프: Stage는 Prim의 계층 트리(씬그래프)다 — /World/Robot/Arm 같은 경로로 객체를 가리킨다. 순회·질의·편집은 Stage를 통해.
  • 편집은 어느 레이어에?: Stage에 변경을 쓰면 현재 편집 대상 레이어(edit target) 에 기록된다 — 기본은 루트 레이어, 바꾸면 다른 레이어에. 이것이 "베이스는 두고 오버라이드 레이어에 쓰기"의 메커니즘(10.3.6).
  • 합성 = 재현 가능: 같은 레이어 세트 → 같은 Stage. 그래서 Nucleus(10.2)가 레이어를 공유하면 모두가 같은 합성 결과를 본다.
  • Isaac Sim의 Stage(9.11): 9.11의 omni.usd.get_context().get_stage()가 이 Stage — 로봇·환경·센서 프림이 사는 씬그래프. 시뮬·렌더가 이 Stage를 본다.

핵심: Stage는 여러 레이어를 합성한 결과인 씬그래프 — 우리가 질의·편집·렌더하는 대상이다. Layer가 재료, Stage가 결과. 편집은 edit target 레이어에 기록되어(베이스 보존), 같은 레이어 세트는 같은 Stage(재현·협업 10.2). Isaac Sim·렌더가 보는 것이 이 Stage(9.11).

10.3.4 Prim — 씬의 노드

Prim(프림, primitive) 은 Stage 씬그래프의 기본 노드 — 메시·라이트·카메라·Xform·로봇이 전부 Prim이다.

   Prim의 구성:

   경로(path)   : 씬그래프 위치 = 네임스페이스 (/World/Robot/Arm/Hand)
   타입(type)   : 스키마(schema) — 무엇인가 (Xform·Mesh·Camera·DistantLight·...)
   계층(children): 자식 Prim들 (트리)
   속성(properties): Attribute·Relationship (10.3.5)
   메타데이터    : kind·active·instanceable 등

   def Xform "World"            ← Prim: 타입 Xform, 이름 World
   {
       def Mesh "Cube" { ... }  ← 자식 Prim: 타입 Mesh
       def DistantLight "Sun" {} ← 자식 Prim: 타입 DistantLight
   }
  • 경로 = 네임스페이스: Prim은 /World/Robot/Arm 같은 경로로 식별된다 — 파일시스템 경로처럼 계층적. 다른 프림 참조·관계가 이 경로로.
  • 타입 = 스키마(schema): Prim의 타입은 스키마로 정해진다 — Xform(변환 그룹)·Mesh(지오메트리)·Camera·DistantLight·PhysicsScene 등. 스키마가 그 프림이 가질 속성·의미를 정의한다(예: Mesh는 points·normals, Camera는 focalLength).
    • typed schema(프림의 정체: Mesh·Xform) vs applied schema(추가 기능: PhysicsRigidBodyAPI·CollisionAPI 등을 적용함 — 물리 9.11). 로봇·물리·렌더 기능이 스키마로 확장된다.
  • 계층(네임스페이스): Prim은 자식을 가져 트리를 이룬다 — 로봇은 링크·조인트 프림의 트리(아티큘레이션 9.11). Xform 프림은 자식의 변환을 묶는다.
  • def·over·class: def(define, 새 프림 정의)·over(override, 기존 프림에 의견만 오버레이하기 — 비파괴 10.3.6)·class(상속용 추상). over가 오버라이드의 문법.
  • API(pxr): stage.GetPrimAtPath("/World/Cube")·UsdGeom.Mesh.Define(stage, path)·prim.GetTypeName(). 스키마별 클래스(UsdGeom.Mesh·UsdLux.DistantLight)로 타입 안전하게.

핵심: Prim은 씬그래프의 노드 — 경로(네임스페이스)·타입(스키마)·계층·속성을 가진다. 메시·라이트·카메라·로봇이 전부 Prim이고, 스키마가 그 정체(typed: Mesh·Xform)와 추가 기능(applied: 물리 API 9.11)을 정의한다. def(정의)·over(오버라이드)·class(추상)로 선언. 경로로 서로를 참조.

10.3.5 속성 — Attribute·Relationship·타임샘플

Prim이 무엇을 담나 — 속성(property)은 두 종류다: 값을 담는 Attribute와 다른 프림을 가리키는 Relationship.

   Prim의 속성(property) 두 종류:

   ① Attribute(속성값) — 타입 있는 이름붙은 값
      예: point3f[] points, float radius, color3f displayColor,
          double3 xformOp:translate, float intensity
      · 타입(float·int·token·array·…), 단일값 또는 배열
      · 타임샘플(time sample) → 애니메이션(시간별 값)

   ② Relationship(관계) — 다른 Prim(들)을 가리킴(경로)
      예: material:binding → /World/Materials/Metal (머티리얼 바인딩)
          물리 조인트의 body0/body1 → 링크 프림들

   def Mesh "Cube" {
       point3f[] points = [...]                 ← Attribute
       color3f[] primvars:displayColor = [(0.8,0.2,0.2)]  ← Attribute
       double3 xformOp:translate = (0,0,1)      ← Attribute(변환)
       uniform token[] xformOpOrder = ["xformOp:translate"]
       rel material:binding = </World/Mat>      ← Relationship
   }
  • Attribute = 타입 있는 값: 지오메트리(points·normals)·변환(xformOp:translate/rotate/scale)·외형(displayColor·intensity)·물리(mass·velocity) 등 그 프림의 데이터. 스키마가 어떤 속성이 있는지 정의. 단일값 또는 배열.
  • 타임샘플 = 애니메이션: Attribute는 시간별 값(time sample) 을 가질 수 있다 — translate를 프레임마다 다르게 → 애니메이션. 로봇 관절 궤적·카메라 무빙·시뮬 기록이 타임샘플(9.12 rosbag 정신의 USD판). 시간 없는 default 값도 있다.
  • Relationship = 프림 가리키기: 값이 아니라 다른 프림(경로)을 가리킨다 — 머티리얼 바인딩(material:binding), 물리 조인트가 잇는 두 바디, 그룹 멤버십 등. 씬의 연결 구조.
  • xformOp(변환): USD에서 변환은 xformOp:translate/rotate/scale 속성 + xformOpOrder(적용 순서)로 표현 — 유연하지만 순서가 중요(함정). UsdGeom.XformCommonAPI로 간편하게.
  • primvars: 프림에 붙는 추가 데이터(displayColor·UV 등) — 렌더·셰이딩에 쓰임.
  • API: prim.GetAttribute("radius").Get()/Set(2.0)·attr.Set(value, time)(타임샘플)·UsdShade로 머티리얼 바인딩.

견해: Prim의 속성은 Attribute(타입 있는 값 — 지오메트리·변환·외형·물리) 와 Relationship(다른 프림 가리킴 — 머티리얼·조인트) 둘이다. Attribute는 타임샘플로 애니메이션(로봇 궤적·시뮬 기록). 변환은 xformOp + 순서로 표현(순서 주의). 스키마(10.3.4)가 어떤 속성이 유효한지 정의 — Mesh엔 points, Camera엔 focalLength. 이 속성들이 씬의 실제 데이터.

10.3.6 Layer — 저장·합성의 단위

Layer(레이어) 는 USD의 저장·합성 단위 — 프림·속성의 "의견(opinion)"을 담은 파일(또는 익명 버퍼)이고, 비파괴 합성의 핵심이다.

Stage 합성 강한 레이어 우선 base.usda (약한 레이어) def Mesh 'Cube' { color = (0.8,0,0) translate = (0,0,1) } override.usda (강한 레이어, 위에 오버레이됨) over 'Cube' { color = (0,0,0.8) ← 덮어씀 } (base는 그대로! translate 유지) 결과: Cube color=(0,0,0.8), translate=(0,0,1)

base는 안 건드린다 — override 레이어만 추가/제거하면 변경을 on/off한다(비파괴).

  • 레이어 = 의견의 묶음: 각 레이어는 프림·속성에 대한 의견(opinion) 을 담는다 — "Cube의 색은 파랑", "translate는 (0,0,1)". 여러 레이어의 의견을 강도 순서로 합성해 Stage를 만든다(강도 규칙 LIVRPS는 10.4).
  • 비파괴 오버라이드(핵심): 강한 레이어(예: 위에 오버레이한 override.usda)의 의견이 약한 레이어(base.usda)를 덮어쓴다 — 단, base 파일은 안 바뀐다. override 레이어를 빼면 원래대로. over 문법으로 "이 프림에 의견만 오버레이하기".
  • 왜 이것이 결정적인가(10.2·9.14·10.8):
    • 협업(Nucleus 10.2): 라이팅 팀은 lighting.usda에, 모델 팀은 model.usda에 의견을 써 서로 안 깨고 합성. 동시 편집이 비파괴라 가능.
    • 도메인 랜덤화(9.14): 베이스 씬 위에 랜덤화 레이어로 마찰·색·위치 변형을 오버레이하고, 빼면 원복 — 베이스 보존.
    • 디지털트윈(10.8): 설계 레이어 위에 운영·센서 레이어를 겹침.
    • 변형(variant 10.4): 한 자산의 여러 버전을 레이어로.
  • 루트·서브레이어·LayerStack: 루트 레이어가 서브레이어(sublayer) 로 다른 레이어를 포함 → LayerStack. (참조·페이로드 등 다른 합성 아크는 10.4.)
  • .usda vs .usdc vs .usd: .usda(ASCII — 사람이 읽고 디버깅), .usdc(crate — 바이너리·빠름·대용량), .usd(둘 중 하나). 개발·디버깅은 .usda, 프로덕션·대용량은 .usdc.

핵심: Layer는 의견(opinion)의 묶음이고, 강한 레이어가 약한 레이어를 비파괴적으로 덮어쓴다(base 보존, override 레이어 추가/제거로 on/off). 이 비파괴 합성이 협업(Nucleus 10.2)·도메인 랜덤화(9.14)·디지털트윈(10.8)·변형(10.4) 의 근거 — "USD가 토대인 이유"의 핵심. .usda(디버깅)/.usdc(프로덕션). 강도 규칙·참조는 10.4.

10.3.7 워크스루 — USD 읽고·쓰고·오버라이드

USD 데이터 모델을 "텍스트로 읽고, Python으로 쓰고, 레이어로 오버라이드" 흐름으로 익힌다.

# base.usda — 사람이 읽는 USD(.usda ASCII)
#usda 1.0
(
    defaultPrim = "World"
    upAxis = "Z"
    metersPerUnit = 1.0
)

def Xform "World"
{
    def Mesh "Cube"
    {
        float3[] extent = [(-1,-1,-1), (1,1,1)]
        point3f[] points = [ (-1,-1,-1), (1,-1,-1), ... ]   # 지오메트리
        color3f[] primvars:displayColor = [(0.8, 0.2, 0.2)] # 빨강
        double3 xformOp:translate = (0, 0, 1)               # 변환
        uniform token[] xformOpOrder = ["xformOp:translate"]
    }
    def DistantLight "Sun" { float inputs:intensity = 1000 }
}
# Python(pxr)으로 읽고 쓰기 — USD API는 비교적 안정적
from pxr import Usd, UsdGeom, UsdLux, Sdf, Gf

# 1) 새 스테이지·프림 만들기
stage = Usd.Stage.CreateNew("base.usda")
UsdGeom.SetStageUpAxis(stage, UsdGeom.Tokens.z)
world = UsdGeom.Xform.Define(stage, "/World")          # Xform 프림
cube  = UsdGeom.Cube.Define(stage, "/World/Cube")       # Cube 프림(스키마)
cube.GetPrim().GetAttribute("size").Set(2.0)            # Attribute 설정
UsdGeom.XformCommonAPI(cube).SetTranslate(Gf.Vec3d(0, 0, 1))
sun = UsdLux.DistantLight.Define(stage, "/World/Sun")
sun.GetIntensityAttr().Set(1000)
stage.SetDefaultPrim(world.GetPrim())
stage.GetRootLayer().Save()                             # base.usda에 저장

# 2) 읽기·순회
stage2 = Usd.Stage.Open("base.usda")
for prim in stage2.Traverse():                          # 씬그래프 순회
    print(prim.GetPath(), prim.GetTypeName())           # /World Xform, /World/Cube Cube ...
# 3) 비파괴 오버라이드 — 별도 레이어에서 색만 바꿈(base는 그대로, 10.3.6)
#    핵심: override를 '루트'로 두고 base를 '서브레이어'로 추가해야 override가 base를 이긴다.
#    (레이어 스택에서 루트의 직접 의견 > 서브레이어 → base 위에 단순 append하면 안 이김)
over_layer = Sdf.Layer.CreateNew("override.usda")       # 강한 레이어(루트가 됨)
over_layer.subLayerPaths.append("base.usda")           # base를 더 약한 서브레이어로 추가함
stage = Usd.Stage.Open(over_layer)                     # override.usda 루트 → base보다 강함
stage.SetEditTarget(over_layer)                        # 편집 대상 = override 레이어
cube = stage.GetPrimAtPath("/World/Cube")
cube.GetAttribute("primvars:displayColor").Set([(0, 0, 0.8)])  # 파랑으로 override(루트가 base 이김)
over_layer.Save()
# → base.usda는 빨강 그대로, override.usda(루트)만 파랑 의견. 빼면 원복(비파괴)
   체크포인트:
     · .usda를 텍스트로 열어 Prim(def)·속성·변환을 읽을 수 있나(디버깅)
     · Traverse로 씬그래프 순회·타입 확인
     · edit target을 override 레이어로 두면 base 보존하며 덮어쓰기(10.3.6)
     · 같은 레이어 세트 → 같은 Stage(재현·협업 10.2)
  • .usda로 디버깅: USD가 이상할 때 .usda(텍스트)로 열어 프림·속성·합성을 눈으로 — 가장 강력한 디버깅(바이너리 .usdc는 usdcat으로 텍스트 변환). 변환 순서(xformOpOrder)·머티리얼 바인딩·스키마를 확인.
  • edit target이 핵심: 어느 레이어에 쓸지(SetEditTarget)가 "베이스 보존 오버라이드"의 메커니즘 — Isaac Sim·도메인 랜덤화(9.14)·세션 변경이 이걸로 베이스를 안 깬다.
  • usdview·usdcat 도구: usdview(씬 시각·검사)·usdcat(텍스트 출력)·usdchecker(검증) 등 USD CLI 도구로 검사·디버깅.

견해: USD 실습의 핵심은 ① .usda를 텍스트로 읽고 쓰기(프림·속성·변환 — 디버깅) ② Traverse로 씬그래프 순회 ③ edit target을 override 레이어로 두어 베이스 보존 비파괴 오버라이드(10.3.6). USD가 이상하면 .usda(또는 usdcat)로 열어 합성 결과를 눈으로. 이 데이터 모델 위에서 Isaac Sim(9.11)·협업(10.2)·랜덤화(9.14)가 실행된다.

10.3.8 중간 점검 (체크포인트)

  • [ ] USD가 파일 포맷이 아니라 비파괴 합성 씬 시스템이고, 왜 Omniverse·로봇·트윈이 그 위에 서는지 안다.
  • [ ] Stage = 레이어 합성 결과(씬그래프), 우리가 질의·편집·렌더하는 대상임을 안다.
  • [ ] Prim = 경로·타입(스키마)·계층·속성을 가진 노드이고, typed/applied 스키마(물리 API 9.11)를 안다.
  • [ ] 속성이 Attribute(타입 값·타임샘플=애니메이션)·Relationship(프림 가리킴) 둘임을 안다.
  • [ ] Layer = 의견 묶음, 강한 레이어가 약한 레이어를 비파괴 오버라이드(base 보존)함과 그 협업·랜덤화·트윈 의의를 안다.
  • [ ] .usda(디버깅)/.usdc(프로덕션), edit target으로 베이스 보존 오버라이드, usdview/usdcat을 안다.

증상→의심: 변경이 베이스를 덮어씀(원복 불가) → edit target이 베이스 레이어 → override 레이어로(10.3.6). 프림이 안 보임/타입 이상 → 스키마·경로·active·합성 순서 → .usda/usdview 검사. 변환이 이상 → xformOp 순서(xformOpOrder)·단위(metersPerUnit)·upAxis → 확인. 머티리얼이 안 붙음 → Relationship(material:binding) 경로 → usdview. USD가 깨짐/안 열림 → usdchecker·.usda 텍스트 검사. 협업서 충돌 → 같은 레이어 동시 쓰기 → 레이어 분리(10.2). 대용량 느림 → .usda 대신 .usdc·페이로드(10.4).

10.3.9 트레이드오프·대안

결정트레이드오프
USD(합성) vs 단일 파일 포맷(FBX·glTF)비파괴·협업·재사용·스케일 vs 단순·즉시·널리 지원
.usda(ASCII) vs .usdc(crate)사람이 읽음·디버깅·diff vs 빠름·작음·대용량
오버라이드 레이어 vs 직접 편집비파괴·재사용·실험 vs 단순(파괴적)
typed schema vs 일반 프림의미·도구 지원 vs 유연
참조/페이로드(10.4) vs 인라인재사용·지연로드·스케일 vs 단순(다음 장)

견해: 여러 도구·팀이 비파괴적으로 협업하고 자산을 재사용하며 대규모 씬을 다루려면 USD가 강하다 — Omniverse·시뮬·트윈의 토대(10.1·10.2·10.8)인 이유. 단 단일 자산 교환·단순 뷰어엔 FBX·glTF가 더 간단·널리 지원될 수 있고, USD는 합성·레이어 개념의 학습 곡선이 있다. 개발·디버깅엔 .usda(텍스트), 프로덕션·대용량엔 .usdc. 변경은 오버라이드 레이어로 비파괴(베이스 보존) — 협업·랜덤화(9.14)·트윈의 핵심. 합성의 강도·재사용 메커니즘(참조·변형)은 10.4에서.

비엔비디아 정직: USD는 픽사 발 오픈 표준(AOUSD) 으로 NVIDIA 전유물이 아니며, 대안·관련 포맷도 있다 — glTF(웹·경량 전송 표준)·FBX(DCC 교환, 폐쇄적)·Alembic(베이크된 지오메트리·VFX)·MaterialX(머티리얼, USD와 상호보완). USD의 강점은 합성(비파괴 레이어·참조·변형)·대규모 협업·스키마 확장성이라 씬 조립·협업·파이프라인에 강하고, glTF는 최종 전송·웹, Alembic은 베이크 캐시에 강하다. NVIDIA(Omniverse)는 USD를 잘 구현·확장·실시간 협업(10.2) 한 것이지 USD를 소유하지 않는다 — 다른 도구도 USD를 쓴다(10.2 상호운용). 스키마·API·버전은 그 시점 확인.

10.3.10 흔한 함정

  • USD를 단순 파일 포맷으로 취급. 합성·레이어를 모르면 협업·오버라이드·재사용을 못 씀 → 합성 시스템으로 이해(10.3.2·10.3.6).
  • 베이스 레이어에 직접 편집. edit target이 베이스면 원본 파괴·원복 불가 → 오버라이드 레이어로(10.3.6).
  • xformOp 순서·단위 무시. translate/rotate/scale 순서(xformOpOrder)·metersPerUnit·upAxis가 틀리면 물체가 잘못된 위치/크기 → .usda 확인.
  • .usdc만 보고 디버깅 포기. 바이너리라 안 읽힘 → usdcat으로 텍스트·usdview로 시각.
  • 스키마 무시한 프림. 타입 없이 속성만 넣으면 도구·렌더가 해석 못 함 → 적절한 스키마(Mesh·Xform·물리 API 9.11).
  • Relationship 경로 오타. material:binding·조인트 타깃 경로가 틀리면 안 붙음 → usdview로 관계 확인.
  • 타임샘플 vs default 혼동. 애니메이션(타임샘플)과 정적(default) 값 혼용 → 의도대로 설정.
  • 대용량을 .usda로. 텍스트라 느리고 큼 → 프로덕션은 .usdc·페이로드(10.4).
  • 합성 강도 가정. 어느 레이어가 이기는지(LIVRPS)를 모르고 추측 → 10.4에서 정확히.
  • USD를 NVIDIA 전유물로 오해. 오픈 표준(AOUSD) → 다른 도구도 사용(10.2 상호운용).

10.3.11 연습문제

연습 1 (4계층). USD의 Stage·Prim·Property·Layer의 관계를 설명하고, "Stage는 결과, Layer는 재료"라는 말의 의미와 그것이 왜 USD가 단순 파일 포맷과 다른 핵심인지 답하라.

정답

네 계층의 관계: Layer(레이어) = 저장·합성의 단위(파일 또는 익명 버퍼)로, 프림·속성에 대한 의견(opinion) 을 담는다("Cube의 색은 파랑"). Stage(스테이지) = 하나 이상의 레이어를 합성한 결과인 씬그래프 — 우리가 질의·편집·렌더하는 대상. Prim(프림) = Stage 씬그래프의 노드(메시·라이트·로봇)로 경로·타입(스키마)·계층을 가진다. Property(속성) = Prim이 담는 데이터 — Attribute(타입 값)·Relationship(프림 가리킴). 즉 Layer(들) → 합성 → Stage(Prim 트리, 각 Prim에 Property). "Stage는 결과, Layer는 재료": Stage는 직접 저장되는 단일 파일이 아니라, 레이어들을 합성한 런타임 뷰다. 레이어(base.usda + override.usda)를 열어 강도 순서로 합치면 Stage가 생긴다. 같은 레이어 세트 → 같은 Stage(재현). 편집은 edit target 레이어에 기록(베이스 보존). 왜 단순 포맷과 다른 핵심인가: FBX·glTF는 "씬 하나를 한 파일에 일괄 직렬화" — 하나의 묶음이라 편집이 파괴적(원본 수정)이고 협업·재사용·오버라이드가 어렵다. USD는 씬을 여러 레이어의 의견으로 분해하고 합성한다 → ① 비파괴 — 베이스를 안 건드리고 강한 레이어에서 덮어쓰기(원복 가능) ② 협업 — 여럿이 다른 레이어에 동시 작성(서로 안 깸, Nucleus 10.2) ③ 재사용 — 참조로 자산 공유(10.4) ④ 스케일 — 대규모 씬을 레이어·지연로드로. "Stage=결과, Layer=재료"의 분리가 이 모든 것을 가능케 한다 — 결과(Stage)를 고정 저장하는 대신 재료(Layer)를 조합하니, 재료를 더하고 빼고 겹쳐 비파괴적으로 변형·협업·재사용. 이것이 USD가 "포맷이 아니라 합성 시스템"인 이유이자 Omniverse·시뮬·트윈(10.1·10.2·10.8)의 토대.

연습 2 (스키마). Prim의 타입(스키마)이 무엇이고 왜 중요한지 설명하고, typed schema와 applied schema의 차이를 로봇 시뮬(9.11) 예로 답하라.

정답

스키마란: Prim의 타입은 스키마(schema) 로 정해진다 — 스키마는 그 프림이 무엇인지와 어떤 속성·의미를 갖는지 정의한다. 예: Mesh 스키마는 points·normals·faceVertexIndices를, Camera는 focalLength·clippingRange를, DistantLight는 intensity를 정의. 왜 중요한가: ① 의미 부여 — "이 프림은 메시/카메라/라이트"라는 정체를 줘 도구·렌더가 올바로 해석. ② 속성 규약 — 어떤 속성이 유효한지 정의해 일관성(임의의 속성을 넣는 것이 아니라 스키마가 정한 것). ③ 도구 지원 — 스키마를 아는 도구가 적절히 처리(렌더러가 Mesh를 그리고 Camera로 뷰). ④ 확장성 — 새 도메인(물리·로봇)을 스키마로 추가. typed vs applied schema: typed schema = 프림의 정체(무엇인가) — Mesh·Xform·Camera·DistantLight. 프림 하나당 하나의 타입(def Mesh "Cube"). applied schema = 프림에 추가 기능(API)을 적용함 — 기존 타입을 바꾸지 않고 능력을 더함. 로봇 시뮬(9.11) 예: 로봇 링크는 typed schema Mesh(또는 Xform 아래 Mesh)로 지오메트리를 갖고, 거기에 applied schema PhysicsRigidBodyAPI(강체 — 질량·속도)·PhysicsCollisionAPI(충돌 모양)를 적용해 물리 객체로 만든다. 로봇 전체는 PhysicsArticulationRootAPI를 적용한 프림 아래 링크·조인트(PhysicsJoint 타입 + 드라이브 API). 즉 "무엇인가"는 typed(Mesh·Xform), "어떤 능력을 추가하나"는 applied(물리·충돌·머티리얼 API). URDF→USD 임포트(9.11)가 이 스키마들을 붙여 PhysX가 시뮬할 아티큘레이션을 만든다. 핵심: 스키마가 프림의 정체·속성·기능을 정의하고, applied schema로 물리·렌더 능력을 비파괴적으로 확장 → USD가 로봇·물리·다양한 도메인을 담는 확장 가능 데이터 모델이 된다. 스키마 없이 속성만 넣으면 도구가 해석 못 함(함정).

연습 3 (Attribute vs Relationship·타임샘플). Attribute와 Relationship의 차이를 예로 설명하고, 타임샘플이 무엇이며 로봇·시뮬에서 어떻게 쓰이는지 답하라.

정답

Attribute vs Relationship: Attribute(속성값) = 타입 있는 이름붙은 값 — 그 프림의 데이터를 직접 담는다. 예: point3f[] points(지오메트리), double3 xformOp:translate(변환), color3f displayColor(색), float intensity(밝기), float mass(질량). 타입(float·int·token·array…)이 있고 단일값 또는 배열. Relationship(관계) = 값이 아니라 다른 Prim(들)을 가리킴(경로). 예: material:binding → /World/Materials/Metal(이 메시에 이 머티리얼을 바인딩), 물리 조인트의 body0/body1 → 링크 프림들(이 조인트가 잇는 두 바디), 그룹 멤버십. 즉 Attribute는 "이 프림의 데이터", Relationship은 "이 프림과 다른 프림의 연결". 씬의 데이터는 Attribute, 씬의 연결 구조는 Relationship. 타임샘플(time sample): Attribute는 시간별 값을 가질 수 있다 — translate를 프레임 0에 (0,0,0), 프레임 30에 (1,0,0)…으로 저장하면 애니메이션. 시간 없는 default 값과 구분된다(attr.Set(v) = default, attr.Set(v, time) = 타임샘플). 로봇·시뮬 활용: ① 로봇 관절 궤적 — cuMotion(9.10)이나 RL(9.13)이 만든 관절각 시퀀스를 조인트 각도 Attribute의 타임샘플로 → 로봇 동작 재생. ② 시뮬 기록·재생 — 시뮬 한 에피소드의 모든 프림 변환을 타임샘플로 기록하면 결정적 재생·리뷰(9.12 rosbag·8.14 재시뮬의 USD판). ③ 카메라 무빙·애니메이션 — 카메라 자세 타임샘플. ④ 센서 데이터 시간열. ⑤ 물리 시뮬 베이크 — PhysX 결과를 타임샘플로 구워 재생(물리 재계산 없이). 즉 타임샘플이 USD에 시간 차원을 줘 애니메이션·기록·재생을 표현 — 로봇 동작·시뮬 결과를 담는 그릇. Relationship은 머티리얼·물리 조인트 연결에. 핵심: Attribute(값·타임샘플 애니메이션)·Relationship(프림 연결)이 프림의 데이터와 구조를 이루고, 타임샘플이 시간 의존 데이터(궤적·기록)를 담는다. usdview로 타임샘플·관계를 검사.

연습 4 (비파괴 오버라이드). Layer의 비파괴 오버라이드가 어떻게 동작하는지 설명하고, 이것이 왜 Nucleus 협업(10.2)·도메인 랜덤화(9.14)·디지털트윈(10.8)의 핵심 메커니즘인지 답하라.

정답

동작: 각 레이어는 프림·속성에 대한 의견(opinion) 을 담는다. USD는 여러 레이어를 강도 순서로 합성해 Stage를 만드는데(강도 규칙 LIVRPS는 10.4), 강한 레이어의 의견이 약한 레이어를 이긴다. 예: base.usda(약)가 "Cube 색=빨강, translate=(0,0,1)"을, override.usda(강, 위에 오버레이됨)가 over "Cube" { 색=파랑 }을 담으면, 합성 결과는 색=파랑(override 이김)·translate=(0,0,1)(base 유지, override가 의견 없음). 결정적: base.usda 파일은 바뀌지 않는다 — override 레이어에만 새 의견을 썼다. override 레이어를 빼면 원래(빨강)로. over 문법이 "이 프림에 의견만 오버레이하기"(새로 정의 def가 아니라). edit target(10.3.7)을 override 레이어로 두면 변경이 거기 기록. 왜 세 곳의 핵심인가: ① Nucleus 협업(10.2) — 라이팅 팀은 lighting.usda에, 모델 팀은 model.usda에, 애니 팀은 anim.usda에 각자 의견을 쓴다. 비파괴라 한 팀이 다른 팀 자산을 안 깨고 동시 작성, 합성으로 모두 반영. 단일 파일이면 동시 편집 시 충돌·덮어쓰기. 비파괴 레이어가 실시간 협업을 가능케. ② 도메인 랜덤화(9.14) — 베이스 씬 위에 랜덤화 레이어로 마찰·색·위치·조명 변형을 오버레이한다. 매 에피소드 다른 변형을 override로, 빼면 베이스 원복 — 베이스를 보존하며 수천 변형(9.13 병렬 환경마다). 베이스 파괴 없이 무한 변형. ③ 디지털트윈(10.8) — 설계 레이어(CAD) 위에 운영 레이어(실시간 센서·상태)·what-if 레이어(가상 변경)를 겹친다. 설계는 그대로, 운영 데이터·시나리오를 비파괴로 오버레이해 실물과 동기·실험. 또 변형(variant 10.4) — 한 자산의 여러 버전을 레이어로. 공통 원리: "베이스를 보존하며 변경을 오버레이하고 제거한다"가 협업(여럿이 안 깸)·실험(랜덤화·what-if)·동기(설계+운영)의 토대. 파괴적 편집(단일 파일)이면 이 모두가 불가능 — 누군가의 변경이 원본·남의 작업을 덮어씀. USD의 비파괴 레이어 합성이 Omniverse·시뮬·트윈이 USD 위에 서는 가장 깊은 이유. 정직: 강도 규칙(어느 레이어가 이기나)은 10.4에서 정확히.

연습 5 (디버깅·포맷). USD 씬이 이상할 때(물체가 안 보이거나 잘못된 위치) 어떻게 디버깅하는지 단계로 설명하고, .usda/.usdc/.usd의 차이와 언제 무엇을 쓰는지 답하라.

정답

디버깅 단계: ① .usda(텍스트)로 열어 읽기 — USD의 가장 강력한 디버깅. 바이너리 .usdc면 usdcat scene.usdc 로 텍스트 변환해 본다. 프림(def)·속성·변환·관계를 눈으로. ② 물체가 안 보임 → 프림이 존재하나(경로·오타)·active인가(비활성 프림)·합성에서 다른 레이어가 지웠나(강한 레이어 override)·visibility 속성·스키마 타입이 맞나 → usdview로 씬그래프·합성 검사. ③ 잘못된 위치/크기 → xformOp 순서(xformOpOrder — translate/rotate/scale 적용 순서)·단위(metersPerUnit — m vs cm)·upAxis(Y vs Z) 불일치 → .usda에서 변환·스테이지 메타 확인. 흔한 원인. ④ 머티리얼 안 붙음 → material:binding Relationship 경로 오타·대상 프림 부재 → usdview 관계 검사. ⑤ 합성이 이상(어느 레이어가 이기나) → LayerStack·강도(10.4)·edit target 확인 → usdview의 레이어 스택 뷰. ⑥ 검증 — usdchecker로 USD 유효성·일관성 검사. 도구: usdview(씬 시각·계층·속성·합성 검사 — GUI), usdcat(텍스트 출력), usdchecker(검증), .usda 텍스트 에디터. 포맷 차이: .usda = ASCII(사람이 읽는 텍스트) — 디버깅·diff·버전관리·학습에 좋음, 느리고 큼. .usdc = crate(바이너리) — 빠름·작음·대용량, 사람이 못 읽음(usdcat 필요). .usd = 둘 중 하나(확장자만, 내부는 ASCII 또는 binary) — 유연. 언제 무엇: 개발·디버깅·작은 씬·텍스트 diff가 필요하면 .usda; 프로덕션·대용량·성능·배포는 .usdc; 둘을 섞을 수 있게 .usd. 협업(10.2)에선 작은 오버라이드 레이어는 .usda(읽기·diff), 대용량 지오메트리는 .usdc(성능). 핵심: USD 디버깅의 출발은 .usda(또는 usdcat)로 합성 결과를 텍스트로 보는 것 + usdview로 시각·합성·관계 검사. 변환 문제(순서·단위·축)가 "잘못된 위치"의 단골. 정직: 도구·API는 버전 의존이나 usdview/usdcat/usdchecker는 표준.

10.3.12 요약 · 다음 장

  • USD = 비파괴 합성 씬 시스템(파일 포맷 아님): 여러 레이어의 의견을 합성해 씬을 만든다(베이스 보존·오버라이드·재사용). 픽사 발 오픈 표준(AOUSD) — Omniverse·로봇·트윈(10.1·10.2·10.8)의 토대, NVIDIA 전유물 아님.
  • Stage: 레이어 합성 결과인 씬그래프 — 질의·편집·렌더 대상. Layer가 재료, Stage가 결과. 같은 레이어 → 같은 Stage(재현·협업).
  • Prim: 경로·타입(스키마)·계층·속성의 노드. typed schema(Mesh·Xform — 정체)·applied schema(물리 API 9.11 — 추가 기능). def/over/class.
  • 속성: Attribute(타입 값·타임샘플=애니메이션/기록)·Relationship(프림 가리킴 — 머티리얼·조인트). 변환은 xformOp + 순서.
  • Layer: 의견 묶음, 강한 레이어가 약한 레이어를 비파괴 오버라이드(base 보존). 이것이 협업(10.2)·도메인 랜덤화(9.14)·디지털트윈(10.8) 의 핵심 메커니즘. .usda(디버깅)/.usdc(프로덕션), edit target, usdview/usdcat. 합성 강도·참조는 10.4.

다음 장: 10.4 OpenUSD II — 컴포지션 아크. Stage·Prim·Layer(데이터 모델)를 봤으니, 이제 USD의 합성 메커니즘 으로 깊이 들어간다 — 자산을 재사용하는 참조(reference)·페이로드(payload), 옵션을 담는 변형(variant), 상속·특수화·서브레이어, 그리고 이들의 강도 규칙(LIVRPS). "어느 레이어·아크가 이기는가"를 정확히, 실습으로. 데이터 모델에서 합성의 작동 원리로.