- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在尝试使用模型 I/O 框架导入一个 .obj 文件以在 Scene Kit 中使用。我最初使用简单的 MDLAsset initWithURL: 函数,但在将网格转移到 SCNGeometry 之后,我意识到这个函数正在对网格进行三角剖分,这样每个面都有 3 个唯一的顶点,并且在相同位置的边界面有单独的顶点。这导致我的其他函数出现一些重大问题,因此我尝试通过使用 MDLAsset initWithURL:vertexDescriptor:bufferAllocator:preserveTopology 函数来修复它,preserveTopology 设置为 YES,描述符/分配器设置为默认值 nil。这种保留拓扑解决了我重复顶点的问题,所以面/边都很好,但在这个过程中我丢失了法线数据。
丢失法线,我不是指多重索引,我的意思是在将 preserveTopology 设置为 YES 之后,缓冲区根本不包含任何法线值。而之前是 v1/n1/v2/n2... 步长是 24 字节(3 维 *4 字节/ float * 2 属性),现在缓冲区的前半部分是 v1/v2/...步幅为 12,缓冲区的整个第二半只有 0.0 个 float 。
还有一点奇怪的是,当您查看几何体的 SCNGeometrySources 时,有 2 个来源,1 个具有语义 kGeometrySourceSemanticVertex,1 个具有语义 kGeometrySourceSemanticNormal。你会认为语义顶点源将包含位置数据,而语义法线源将包含法线数据。然而事实并非如此。无论您如何设置 preserveTopology,它们都是大小为包含具有相同值的位置和法线数据的缓冲区。所以当我之前说没有法线数据时,我的意思是这两个缓冲区、语义顶点和语义法线从 v1/n1/v2/n2... 变为 v1/v2/.../(0.0, 0.0, 0.0)/(0.0, 0.0, 0.0)/... 我进入 mdlmesh 的缓冲区(在传输到场景工具包之前)发现了同样的问题,所以问题一定出在 initWithURL,而不是模型 i/o到 scenekit 桥。
所以我认为默认的顶点描述符和缓冲区分配器一定有问题(因为我使用的是 nil)并开始尝试创建自己的匹配这两种可能的数据格式。唉,经过多次尝试,我无法得到有用的东西。
关于我应该如何做到这一点有什么想法吗?如何为 MDLAsset 提供正确的 vertexDescriptor 和 bufferAllocator(我觉得 nil 在这里应该没问题)以导入 .obj 文件?谢谢
最佳答案
带有顶点和法线的 obj 文件有顶点,由 v 线表示,法线由 vn 线表示,面由 f 线表示。
v 和 vn 行将只是您期望的浮点值,f 行的形式为 -
f v0//n0 v1//n1 等
由于 OpenGL 和 Metal 不允许多重索引,您将看到顶点被复制的第一个效果。例如,
f 0//0 1//2 2//0
不能用作顶点缓冲区,因为每个顶点需要不同的索引。所以典型的 OBJ 解析器必须创建新的顶点,让脸变成
f 0//0 1//1 2//2
保留拓扑选项对您没有帮助。它保留了网格的连接性和形状(没有三角剖分发生,共享边保持共享)但它仍然为每个顶点组件强制执行一个索引。
一个解决方案是确保输出 OBJ 文件的工具在导出期间使用单一索引(如果可以的话)。
另一种选择(这不会立即解决问题)是提出在模型 I/O 级别支持多重索引的请求。 SceneKit 仍然需要唯一索引,因为它必须能够渲染。
另一种选择是使用像 PLY 这样没有多重索引的格式。
关于iOS 在不复制顶点的情况下将 .obj 文件导入模型 I/O,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36509005/
我是一名优秀的程序员,十分优秀!