如何在 SceneKit 中使用 OBJ 文件或 CTM 文件而不是 DAE 文件?

Posted

技术标签:

【中文标题】如何在 SceneKit 中使用 OBJ 文件或 CTM 文件而不是 DAE 文件?【英文标题】:How can I use OBJ file or CTM file instead of DAE file in SceneKit? 【发布时间】:2015-05-10 05:10:47 【问题描述】:

我以前在ios上用openGL和metal渲染3d场景,我使用的文件格式是OBJ和CTM。这些天我正在尝试场景工具包。看来 SceneKit 只加载 DAE 文件。我在网上找到的所有demo都使用DAE文件,我在他们的代码中看不到顶点和面的数组。 如何加载 OBJ 文件或 CTM 文件而不是 DAE 文件?

【问题讨论】:

【参考方案1】:

您可以通过编写自己的导入器来做到这一点。看看SCNGeometrySCNGeometrySourceSCNGeometryElement

编辑: 从 iOS 9.0 和 OS X 10.11 SceneKit 开始可以打开 OBJ 文件或 Model I/O 支持的任何其他文件格式。您可以使用以前存在的 API(例如 +sceneNamed:)或新的 +sceneWithMDLAsset: 方法来执行此操作。

【讨论】:

如何从 SCNGeometryElement 导出所有网格? 此答案需要针对 iOS 9 / OS X 10.11 进行更新。【参考方案2】:

编辑:ModelIO 现在可能可以加载 OBJ 文件。我自己没有尝试过这条路。这个答案是在 iOS 9 和 OS X 10.11 之前写的:

SceneKit 无法在 iOS 上加载 DAE 文件,实际上,它实际上将 DAE 文件预编译为 iOS 设备的内部格式。

如果您想将您的 OBJ 转换为 DAE,您可以在 OS X 上编写一个简单的导入器/导出器来执行此操作 - 在 OS X 上,SceneKit 将实际读取 OBJ 文件(它没有记录,但它可以工作)并会编写 DAE。

如果您想尝试自己阅读 OBJ,也可以在 github 上下载“Assimp”项目,但将其放入 SceneKit 对象需要一些工作。

【讨论】:

您现在可以使用 ModelIO 在 iOS(iOS 9+)上加载 OBJ 文件,如@halmueller 的回答中所述。但正如 Wil 所暗示的,您可能不应该。对于您的应用附带的任何资产(甚至通过您的应用在 AppStore 提交后提交,例如托管在您自己的服务器上的附加内容),最好在 Mac 上使用 Xcode 或您自己的基于 ModelIO/SceneKit 的工具进行预处理,然后发送.scn 在该设备上加载速度更快的文件。 这是每个 iOS 开发人员至少了解一点 Mac 开发的一个很好的论据。这种实用程序(在 Mac 上)很方便。 “它实际上将 DAE 文件预编译为 iOS 设备的内部格式”——“内部格式”似乎只是 .scn 格式。可以使用let scene = SCNScene(named: "some_3d_model.dae") 在 iOS 上加载 DAE(刚刚使用 Xcode 8 对照 iOS 10.0.1 检查) 再深入研究一下。 iOS 编译的….app/some_3d_model.dae 是一个二进制plist,其中包含一个zippedData 条目和一堆ZIP 压缩数据,如果base64 解码和未压缩会生成一个contents 文件。 contents 文件是一个二进制 plist,看起来像 SceneKit 内部场景表示 - 有许多与 SceneKit API 1:1 匹配的键,例如 geometryElementsgeometrySourceSCNMaterial 属性名称和sceneattributesnodeTreestartTime 等,如 SCNScene/MDLAsset。 (真正的 .dae 是一个以 <COLLADA> 为根的 XML 文件。)【参考方案3】:

从 iOS 9/OS X 10.11 开始,您可以使用 Model I/O 的 MDLAsset 导入 OBJ 文件(以及一些其他格式)。 How do you convert Wavefront OBJ file to an SCNNode with Model I/O 有示例代码。

【讨论】:

【参考方案4】:

加载 OBJ 文件

就像向 MDLAsset 传递一个有效的 URL 一样简单。

private func nodeForURL(url: NSURL) -> SCNNode

    let asset = MDLAsset(URL: url)
    let object = asset.objectAtIndex(0)
    let node = SCNNode(MDLObject: object)

    return node

这不仅会正确加载.obj 文件,还会加载引用的.mtl 文件。

【讨论】:

【参考方案5】:

有关支持的文件格式的更多信息:

SceneKit 支持以下 3D 文件格式,可以使用 Xcode 中的场景编辑器将其导入.scn 文件:

DAE、OBJ、Alembic、STL 和 PLY 文件。

来源:WWDC 2015 Session "Enhancements to SceneKit" 02:24

【讨论】:

以上是关于如何在 SceneKit 中使用 OBJ 文件或 CTM 文件而不是 DAE 文件?的主要内容,如果未能解决你的问题,请参考以下文章

如何通过SceneKit和Model I / O在.OBJ 3d模型上应用.MTL文件

SceneKit:如何从Google Poly为同一个OBJ文件重新创建照明?

SceneKit NSNode 拆分部分

在 SceneKit/modelIO 中测量 3D-Obj 文件上两点之间的距离并显示它们

.obj 文件未加载所有子网格名称

SceneKit 中的平滑着色