OpenUSD 教程:检查与编写 Prim 属性(Inspecting and Authoring Properties)
2026/9/16 20:13:16 网站建设 项目流程

OpenUSD 教程:检查与编写 Prim 属性(Inspecting and Authoring Properties)

【免费下载链接】OpenUSDUniversal Scene Description项目地址: https://gitcode.com/GitHub_Trending/ope/OpenUSD

本篇指南基于 OpenUSD 官方教程 tut_inspect_and_author_props.rst,带你使用 Python API 完成对场景中 Prim 的几何属性"检查—读取—修改—着色—保存"的完整闭环。读完后你将掌握:如何用UsdPrim枚举一个 Prim 的全部属性名,如何用Usd.Attribute读取回退(fallback)值并写入新值,如何用UsdGeom一级 Schema API 编写displayColor,以及如何将修改导回 USD 层文件。

起始层:HelloWorld.usda

本练习的起点是 Hello World 教程中创建的场景文件,位于 HelloWorld.usda。其内容为:

#usda 1.0 def Xform "hello" { def Sphere "world" { } }

可以看到:/hello是一个 Xform,其子 Prim/hello/world是一个 Sphere,且没有显式编写任何几何属性——这正是理解"回退值"概念的绝佳起点。教程中对应的可运行脚本是 authorProperties.py,每一步操作都可在 Python 交互环境中对照执行。

第一步:打开 Stage 并获取 Prim

from pxr import Usd, Vt stage = Usd.Stage.Open('HelloWorld.usda') xform = stage.GetPrimAtPath('/hello') sphere = stage.GetPrimAtPath('/hello/world')
  • Usd.Stage.Open按路径打开 USD 文件并解析出整个 Stage;
  • GetPrimAtPath通过绝对路径(SdfPath)拿到具体的UsdPrim句柄,后续所有属性操作都基于这两个对象展开。

第二步:枚举 Prim 上的属性名

>>> xform.GetPropertyNames() ['proxyPrim', 'purpose', 'visibility', 'xformOpOrder'] >>> sphere.GetPropertyNames() ['doubleSided', 'extent', 'orientation', 'primvars:displayColor', 'primvars:displayOpacity', 'proxyPrim', 'purpose', 'radius', 'visibility', 'xformOpOrder']

注意两个列表的区别:Sphere 比 Xform 多出doubleSidedextentorientationprimvars:displayColorprimvars:displayOpacityradius等几何属性。这些属性在文件中并未被显式编写,它们是 Schema 声明的"默认存在"的属性——GetPropertyNames返回的是该 Schema 类型可用的全部属性名(包含未在层中 author 的)。

从源码结构看,这一行为实现在 prim.cpp:UsdPrim::GetPropertyNames调用内部的_GetPropertyNames,对 Xformable 等类型会把primDef.GetPropertyNames()(来自 Sdf 层定义)与 Schema 内建属性合并。教程特别提示了一个 API 使用技巧:

API TipGetPropertyNames适合按名称获取单个属性;若需要遍历一个 Prim 的全部属性,更便捷的是UsdPrim::GetPropertiesUsdPrim::GetAttributesUsdPrim::GetRelationships——它们直接返回UsdPropertyUsdAttributeUsdRelationship对象,可无需再按名字查找就直接操作。这三个方法的实现在 prim.cpp 中,内部统一走_GetPropertyNames+_MakeProperties构建对象列表。

第三步:读取 extent 属性,理解回退值

>>> extentAttr = sphere.GetAttribute('extent') >>> extentAttr.Get() Vt.Vec3fArray(2, (Gf.Vec3f(-1.0, -1.0, -1.0), Gf.Vec3f(1.0, 1.0, 1.0)))

这个 2×3 数组是球体轴对齐、对象空间包围盒(extent)的两个端点。由于起始层从未编写过extent,这里返回的是该属性的回退值(fallback value):USD 规定,当场景描述中没有关于某属性值的任何"意见"(opinion)时,属性使用其类型默认的回退值。对 Sphere 而言,radius的回退值是 1.0,因此(-1,-1,-1) ~ (1,1,1)的 extent 与之自洽。

从源码结构看,这类几何包围盒的回退值并非硬编码在 API 里,而是由插件按 Prim 类型注册的ComputeExtent函数计算得出——boundableComputeExtent.cpp 中的_FunctionRegistry维护"类型 → 计算函数"的注册表,UsdGeomBoundable::ComputeExtentFromPlugins据此按time参数动态求值。

另外两点值得记住:

  1. 不带时间参数调用Usd.Attribute.Get()返回 Default 时间的值。属性还可以拥有按时间采样的值——例如为UsdGeom.Meshpoints属性提供时间样本,即可创建动画形变网格(官方文档tut_end_to_end教程演示了该管线的雏形)。
  2. 属性名的字典序:GetPropertyNames的结果默认按字典序排列。

第四步:修改半径,并手动同步 extent

>>> radiusAttr = sphere.GetAttribute('radius') >>> radiusAttr.Set(2) True >>> extentAttr.Set(extentAttr.Get() * 2) True

关键要点:几何包围盒不会随radius修改而自动重算,必须手动把 extent 也更新为新尺寸的 2 倍。Set()Get()同理,只传值不传时间即在 Default 时间编写。此时导出根层内容:

#usda 1.0 def Xform "hello" { def Sphere "world" { float3[] extent = [(-2, -2, -2), (2, 2, 2)] double radius = 2 } }

注意 extent 的类型是float3[](两个Gf.Vec3f),double radius = 2被按 double 类型落盘——类型信息由属性的 Schema 声明决定。

第五步:用 Schema API 编写 displayColor

直接写原始属性名primvars:displayColor很繁琐,OpenUSD 提供一级 Schema API 来隐藏这种细节:

>>> from pxr import UsdGeom >>> sphereSchema = UsdGeom.Sphere(sphere) >>> color = sphereSchema.GetDisplayColorAttr() >>> color.Set([(0,0,1)]) True

UsdGeom.Sphere包装器暴露了GetDisplayColorAttr()等具名访问器,客户端代码无需知道其底层原始名是primvars:displayColor。修改后的场景描述为:

#usda 1.0 def Xform "hello" { def Sphere "world" { float3[] extent = [(-2, -2, -2), (2, 2, 2)] color3f[] primvars:displayColor = [(0, 0, 1)] double radius = 2 } }

注意primvars:displayColor落盘类型为color3f[]——即三元组向量。这是因为该属性既可表示整个 Prim 的统一颜色,也可表示逐元素(如每个 mesh 面)的颜色,因此统一以数组形式承载。该属性在各几何类型上的声明可在 generatedSchema.usda 中检索到,例如 Imageable API 下的color3f[] primvars:displayColor定义。

第六步:保存修改

>>> stage.GetRootLayer().Save()

Save()把内存中的根层写回磁盘文件。在 usdview 中打开该文件,相机自动框选几何体;由于半径从 1 变为 2,球体比 Hello World 教程中更大,可在 Attribute browser 中检查属性值加以确认。

进一步阅读

  • UsdProperty:访问属性及其公共 metadata 的编写与查询基类;
  • UsdAttribute:在UsdProperty基础上细化,提供对带类型、按时间采样的属性数据的专用 API;
  • UsdRelationship:在UsdProperty基础上细化,提供对其他 Prim/属性的目标(target)解析,支持沿关系链稳健解析;
  • 属性默认按字典序排列,可用UsdPrim::SetPropertyOrder显式指定顺序。

以上三个类族(UsdProperty/UsdAttribute/UsdRelationship)的 C++ 实现集中在 pxr/usd/usd 目录下,是理解 USD 属性编写体系最直接的入口。

小结

本教程展示了 USD 属性操作的标准工作流:Stage.OpenGetPrimAtPathGetPropertyNames/GetProperties枚举 →GetAttribute+Get()读值(注意回退值语义)→Set()写值(注意 extent 需手动维护)→ 用UsdGeomSchema API 编写着色属性 →GetRootLayer().Save()持久化。配套的可执行脚本 authorProperties.py 内置了各步骤的断言校验(如属性名列表、extent 回退值),适合作为回归验证或二次开发的起点。

【免费下载链接】OpenUSDUniversal Scene Description项目地址: https://gitcode.com/GitHub_Trending/ope/OpenUSD

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询