如何在 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】:您可以通过编写自己的导入器来做到这一点。看看SCNGeometry
、SCNGeometrySource
和SCNGeometryElement
。
编辑: 从 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 匹配的键,例如 geometryElements
、geometrySource
、SCNMaterial
属性名称和scene
与 attributes
、nodeTree
、startTime
等,如 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文件重新创建照明?