Skip to content

Instantly share code, notes, and snippets.

@2youyou2
Last active July 6, 2024 23:30
Show Gist options
  • Save 2youyou2/51eedb23b6488216f3650f6224a8e38e to your computer and use it in GitHub Desktop.
Save 2youyou2/51eedb23b6488216f3650f6224a8e38e to your computer and use it in GitHub Desktop.
USD File format
## USD 格式 特色
@2youyou2
Copy link
Author

2youyou2 commented Apr 12, 2020

USD

USD 是通用场景描述(Universal Scene Description)的缩写,他有两种主要的文件格式 USDA 和 USDC。

USD 最早是设计给视觉特效和动画工业领域在不同软件工具间转换用的,直到苹果决定采用 USDZ 作为所有3D内容的主要文件格式,USD 才开始更广泛的被使用。

https://graphics.pixar.com/usd/overview.html#USDFeatureSpecification-ASCIIvsBinary

USDA:

  • 人类可阅读的文本格式
  • 可以方便的进行 debug。
  • 存储 references, variation and small data values 会更有效。
  • 当打开文件的时候就全部读进内存中

image

image

USDC:

  • 二进制格式(Crate File Format)
  • 打开的时候只读入prim和property的层级关系

image

  • 零拷贝数组:内存映射数据
    • 指向操作系统页面缓存中的内存,操作系统按需获取
  • 在保存时消除重复数据
  • 按时间码按递增的顺序分组的数据
    • 渲染读取局部数据
    • 回放的时候读取序列数据

USDZ

  • 就是 zip 格式,但是是无损零压缩的
  • 与苹果联合开发,用于网络传输
  • 包括了usd文件和所需要的贴图等各种资产
  • 多用于vfx生产中的:在不同部门或公司之间打包和分享资产

使用 SDK 生成

提供了一套 python 的 api 来帮助生成文件。

image

优点 / 缺点

https://www.threekit.com/blog/should-you-use-the-usd-and-usdz-3d-file-formats

优点

  • 支持非常多特性
    支持描述 3D 模型,场景层级,材质,光照,动画,骨骼,蒙皮等等。如果你在一个编辑器的数据想转到另一个工具里面,而这个工具支持 USD 格式,那么转换就会很容易。
  • 支持现代化特性
    USD 支持最新的 PBR 材质和光照定义,它也没有几十年前流行但现在普遍不使用的遗留功能,比如 FBX 对 NURBS surfaces 的支持。
  • Separate Position, UV and Normal Topologies
    Enables the storage of both position, UV and normal data that has different topology, This is great for high quality modeling tools, and enables complex features like accurate subdivision surfaces.
  • 非常快
    因为 USD 充分使用了高效的二进制格式,他在读写方面是很快的,在存储空间方面也很有优势。二进制读取一般都很复杂,但是 USD SDK 隐藏了这一个问题。

缺点

  • 兼容性没那么好
    在 Pixar 工作室内部,USD 格式在他们内部的工具集里面兼容性很好,但是在 Pixar 之外就没那么好了。特别是,在皮克斯工作室之外最常见的支持USDZ的软件是苹果的。不幸的是,苹果 USDZ 功能的实现是非常片面的,并且这些限制都没有文档提供。
    这意味着,一个标准的按照官方文档描述导出的 USD or USDZ 文件可能不能正确的被苹果的软件导入,即使被导入了,表现可能也是不对的。
  • 文件比较大
    USD 格式是被设计用于动画电影制作上的,而不太关心和远端(通过网络)传输数据的速度和效率。具体来说,USDZ没有采用3D几何特定的压缩算法,而相比较 glTF 会用 DRACO 压缩来减少体积。
    有趣的是,尽管USDZ文件使用一个zip文件容器将所有组件文件打包到一个包中,但它目前不允许启用zip压缩特性来减小文件大小。

总结

如果您从事电影制作,特别是电脑动画电影制作,并且您的工具集支持 USDZ,那么使用 USDZ 作为传输数据的工具是一个很好的选择。

如果您需要将数据传输到将在苹果设备上运行的软件或使用苹果基于 web 的 Quicklook AR 功能,使用 USDZ 也是一个不错的选择,这是必须的,但是要注意苹果与官方USD规范的重大不兼容性。

对于大多数其他应用程序,USDZ并不是最好的文件格式选择,通常 glTF 或 FBX 更合适。

@2youyou2
Copy link
Author

2youyou2 commented Apr 13, 2020

USD 格式 特色

Composition System

USD的合成系统有着相当长的历史。它最初版本是皮克斯in-house动画软件“Presto”的一部分,最开始使用是2012年上映的影片《Brave》。这个最初版本一直开发和维护到现在,成为了Presto和USD的核心。

合成(Composition),让用户可以将他们的来自各种数据源(也可以理解为之前讲过的Layer)合成为一个完整的场景。这对于数字内容生产流程非常有用,因为它允许多个艺术家工作在同一资产上,提高了并行生产的效率。

合成允许你从非常小的资产开始构建资产,然后小的资产组合成中等大小的资产,之后中的大小的资产组合成完整的场景。它允许你进行非破坏性的复写(non-destructive override),这样,你就可以在不破坏当前资产的情况下,修改资产的外观,属性等等。例如:《玩具总动员 4》中的古董商场,就是通过包括引用(reference)在内的多种操作符,用许多很小的模型拼装起来的巨大而复杂的环境。

image

合成(Composition )是通过写在usd文件中的一系列的操作符号(operators (or “arcs”))来完成的。在运行时,usd的合成引擎运算这些操作符,并最终将合成的场景呈现给用户。这里列出来的就是usd中的合成操作符(composition arcs)。

Sublayer

image
子层(Sublayers)是最简单的合成操作符(composition arc)。子层的作用是:允许你将场景描述合并到其它层上。

image

这里的根层定义了下面子层的顺序,形如一个有排过序的树。合成过程:进行深度优先遍历这个树,然后形成一个有关层的列表,我们称之为”层堆栈(layer stack)“,根层的位置在堆的最上端。

image

在这个例子中:DukeCaboom在layout层被放置在某个位置。现在,假设某个新的艺术家进如项目中,他可以通过修改上层的shot.usd层中“xformOp.translate”和 “xformOp.rotate”属性来实现位移和旋转。我们现在在层堆栈(layer stack)中有两个有关旋转属性(xformOp.translate)的观点(opinions),但是shot.usd在shot_layer.usd层上,所以shot.usd的观点更强。这就是一个非破坏覆写(non-destructive override)的例子,我们修改了DukeCaboom的位置,但并没有改变它之前的值。

References

image

引用(reference)合成操作符用来将其它层堆栈(layer stack)中的基础图元(prim)引入到我们的场景图中。这就是如何用小的资产来构建大的资产的方式。

image

假设DukeCaboom模型是通过一个DukeCaboom.usd层创建出来的。这个模型本身可能也是由几个子层和一些其它的合成操作完成的。但是这里为了简化,就认为只有一层。

image

就像是子层(sublayers),我们也可以对引用操作符进行非破坏性覆写(non-destructive overrides )。例如,我们可以在shot_layout.usd层声明另外一套点集(这里指的是对DukeCaboom中的points进行覆写),然后由于上层的观点更强,那么引用的资产中的属性将被覆盖掉。后面我们会讨论到:覆写的强弱顺序。这里需要强调的是,你可以将同一个资产引用到某一个镜头很多次。例如,当构建“复古商场”的环境的时候,我们有很多道具模型被引用了好几次,这样就等于,我们将这些道具复制了很多次,然后将其分布在场景的各个位置,用来搭建场景。

Sublayer 和 Reference 区别?

https://graphics.pixar.com/usd/docs/USD-Frequently-Asked-Questions.html#USDFrequentlyAskedQuestions-IhavesomelayersIwanttocombine:ShouldIuseSubLayersorReferences?

讨论里面介绍了什么时候该用哪个操作符,但是我是没怎么理解里面说的具体区别,需要后续进一步使用的时候再研究下细节。
感觉区别像是下面的代码一样?:

Object.assign({ a: 1 }, { b: 2, c: 3 })

Object.setPrototypeOf({ a: 1 }, { b: 2, c: 3 })

Payloads

image

下面介绍负载(payloads)。引用(Reference)让我们可以通过小的组件组成大的资产集合体。但是,有的时候需要让用户在运行时决定哪些内容要进行合成。负载(payloads)合成操作符提供了我们这种能力,它可以在运行时通过各种API调用选择加载或卸载的引用。

image

假设我们使用负载(payload)合成操作符将DukeCaboom引入到我们的镜头中,而不是像以前那样使用引用。当加载负载(payload)时,合成的结果看起来就像我们使用引用时的结果一样。

image

但是假设有一个布景师在做“复古商场”的布景,他们不需要去看DukeCaboom。在运行时,他们可以选择不加载DukeCaboom的负载(payload)。在这种情况下,负载的内容将在合成期间被忽略,从而节省内存和运行时成本。注意,负载(payload)加载/卸载是一个运行时flag,因此加载/卸载负载不会对层产生任何更改。

image

下一个要提到的合成操作符是“变体(variant)”。变体允许用户在单个资产中打包一组备选方案。用户创建在资产中包含“变体(variant)”的“变量集(variant sets)”,然后编写“变量选择(variant selections)”以选择在合成过程中应该具体使用哪个变体。右边的示例显示了我们的DukeCaboom资产,其中有一个变量集“Cape”,允许用户在“Cape”中选择具体使用哪个变体,例子中使用的是一个名字叫做“WhiteCape”的变体。

image

当我们将这个DukeCaboom资产引用到我们的镜头中时,合成操作会将“WhiteCape”变体下的所有内容都引入到合成场景图(composed scenegraph)中,因为这是资产中已定义好的的变体选择(variant selection)。

image

但是,我们可以在shot_layout层中创建不同的变体选择(variant selection),比如Cape=RedCape。此选择将覆盖资源中定义的选择,因此我们的合成场景图将以RedCape做为最后合成的结果。

Inherits

image

接下来要讨论的是继承(inherits)。继承允许您以最小的方式对给定分类的所有基础容器(prims)执行大规模覆盖。与面向对象中的继承概念一致。

image

比如说,在“复古商场”的场景中,我们想有一堆不同的书散落在各处。我们可以使用引用(reference)的方法引入两种不同资产。但是假设在“复古商场”的场景中,我想对所有的书应用覆盖,例如,假设我希望所有的书都是红色的。

image

我们可以这样做的一种方法是在“复古商场”的场景中中的每本书上创建一个覆盖,如下所示。这给了我们我们想要的结果,但由于一些原因并不理想。这是不可扩展的——如果你有大量的书在场景中,你必须找到他们所有并对他们声明相同的覆盖。如果你把另一本书放进书包,你也要记得用同样的颜色。这大大限制了扩展性。

image

我们可以使用继承(inherit)合成操作符来解决这个问题。在我们的两个资产中,我们声明将继承(inherit)合成操作符应用给一个名为“class_Book”的基础容器上。名字可以是任意的,但重要的是它们要继承于同一个操作符。然后在“复古商场”的场景中,我们可以在“class_ Book”上创建color=red观点(opinion),它们将被继承到所有的书中。这解决了前面方法面临的问题。还要注意的是,我们不必在“复古商场”的场景中编写继承(inherit)合成操作符,因为它们本身就是图书资产的一部分了。

image

但是我们可以覆写镜头中类的观点(opinion),把所有的书都改成蓝色。因此我们可以看到,继承是一种非常强大的机制,可以将我们的修改广播到受影响的基础容器(prim)中。

Specializes

image

最后一个要讨论的合成操作符是“特化(specialize)”。这是合成引擎的最新添加,是为了帮助USD定义材料库而开发的。这个弧的行为类似于继承,但具有不同的强度排序规则:被特化出来的容器的观点强于源来的观点。

image

在我们的SciFiBook资产中,我们希望为书页定义一组材料。我们有一种基本的“纸”材料,它定义了一些共同的属性,还有两种其他类型的纸,它们都继承了原始材料。光面纸总是比普通纸更亮,所以对于“光面纸”材质,我们要指定比普通纸更高的光泽度值。当我们将其引用到“复古商场”场景中时,合成结果如下所示:paper和notepaper材料的光泽度值为0.2,GlossyPaper 的光泽度为1.0。

image

现在假设在“复古商场”场景中,我们希望这本书中的常规页面稍微亮一点,所以我们重写复古商场”场景层中的值。由于继承行为,此值将覆盖以前的所有亮度值。从概念上讲,这对NotePaper来说是有意义的,因为我们没有在那里指定一个值——我们希望它像基本的纸张材料一样有光泽。但这不是我们想要的GlossyPaper。我们已经通过在书中指定光泽度重新定义了光泽度纸张材料,我们不希望对基本纸张的光泽度进行任何更改来覆盖这一点。

image

如果我们使用特化(specialize)替换继承(inherit),我们就能得到我们想要的行为。即特化出来的GlossyPaper的观点强于Paper的观点。前面之所以光泽度被覆盖,是因为:AntiquesMall_set.usd中的book1引用了SciFiBook.usd,所以AntiquesMall_set中的光泽度观点强于下面的引用,NotePaper没有覆写被继承类,所以,值是受到上层观点的影响。

Paper:
http://graphics.pixar.com/usd/files/Siggraph2019_USD%20Composition.pdf
https://zhuanlan.zhihu.com/p/100091392

@2youyou2
Copy link
Author

Unity 支持情况

Unity 支持导入 .usda 格式(不支持导入 .usdz 格式)到编辑器里面来使用

Unity 支持导出场景到 .usdz 格式,但是如果有绑定骨骼动画的话,导出的 .usdz 格式在 Quick Look 是不能正常播放的。

根据看到的文章说:

A standard USD or USDZ file exported according to the official specifications will not load into Apple software or if it does, it likely will look incorrect, especially with regards to materials. As such, one needs to know that the consumer of the USDZ file is an Apple device and thus export within the limitations of Apple’s software

相关链接:

https://blogs.unity3d.com/cn/2019/03/28/pixars-universal-scene-description-for-unity-out-in-preview/

@2youyou2
Copy link
Author

系统支持情况

测试了苹果 12.x, 13.3, 13.4 几个版本的 safari quick look。

12.x 不支持预览。
13.3 预览最新 Reality Composer 做出来的会出现显示不全等问题。
13.4 能稳定运行预览

设备感知能力

测试 iphone 7 单摄像头通常识别锚点的速度比较慢,而相同情况下 iphone xs 双摄像头会快很多

@2youyou2
Copy link
Author

格式转换工具

苹果提供了一套 python 工具 USDPython 来进行 usdz 格式相关的操作,使用他可以将其他 3D 文件转换到 usdz 格式,也可以在 usd 内部 usdc 与 usda 两种格式间相互转换,还有一些其他的功能。

以下是使用此工具需要配置的基本环境变量:

export PYTHONPATH=/Applications/usdpython/USD/lib/python:$PYTHONPATH
export PATH=/Applications/usdpython/USD/lib/usd:$PATH
export PATH=/Applications/usdpython/USD:$PATH
export PATH=/Applications/usdpython/USD/lib:$PATH

如果需要使用 fbx 转换到 usdz 的功能,需要下载 python fbx 工具。

python fbx 下载安装是会自动安装到 Applications/Autodesk 路径里面,这些路径也需要配置到环境变量里面。

export PYTHONPATH=/Applications/Autodesk/FBXPythonBindings:$PYTHONPATH
export PYTHONPATH="/Applications/Autodesk/FBX Python SDK/2020.0.1/lib/Python27_ub:$PYTHONPATH"

一些使用命令可供参考:

// usda 转到 usdz
./usdcat -o test2.usda test2.usdz 

// fbx 转到 usdz
./usdzconvert model.fbx

更多工具介绍:

https://graphics.pixar.com/usd/docs/USD-Toolset.html

@2youyou2
Copy link
Author

Reality Composer MAC 和 iOS 上都提供了程序进行创作编辑。MAC 上编辑的场景可以直接推送到 iOS 上继续编辑。

iOS 上需要升级系统到 13.4 才能使用 Reality Composer,而 Xcode 需要升级到 11.4 才支持将场景或者项目导出为 USDZ 格式。

Reality Composer 主要由几部分构成:锚点,行为,还有场景编辑。

锚点

锚点指的是 AR 扫描图像时识别出来与给定项目匹配可以挂接场景的位置。

目前提供的锚点有:

  • 水平
  • 竖直
  • 图像
  • 面孔
  • 对象

行为

其实就是触发器,当触发一个条件时调用指定的行为。

内置触发器

  • 默认提供了一些触发器与特定行为的组合
    image

  • 也可以创建自定义行为,在这里面可以自由组合内置触发器与内置行为。

    • 内置触发器其实还比较少
      image
    • 内置行为也比较少,只有一些位移,缩放,隐藏显示,切换场景等简单操作

image

image

场景编辑

Reality Composer 提供的场景编辑很弱,没有 hierarchy,只能点击场景中的物体来编辑属性,物体可以编辑的功能大概就是位置变换,材质,物理行为几个。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment