我尝试使用Model I / O框架导入.obj文件以在Scene Kit中使用。我最初使用简单的MDLAsset initWithURL:函数,但是在将网格转移到SCNGeometry之后,我意识到这个函数是对网格进行三角化,这样每个面都有3个唯一的顶点,并且在边界面的同一位置有单独的顶点。这导致了我的其他函数的一些主要问题,所以我尝试通过使用MDLAsset initWithURL来修复它:vertexDescriptor:bufferAllocator:preserveTopology函数,其中preserveTopology设置为YES,描述符/ allocator设置为默认值为nil。这个保留拓扑解决了我复制顶点的问题,所以面/边都很好,但在这个过程中我丢失了法线数据。
通过丢失法线,我不是指多重索引,我的意思是在将preserveTopology设置为YES后,缓冲区根本不包含任何法线值。而在它之前是v1 / n1 / v2 / n2 ...并且步幅是24字节(3维* 4字节/浮点数* 2属性),现在缓冲区的前半部分是v1 / v2 / ... 12的步幅和缓冲区的整个后半部分只有0.0浮点数。
同样奇怪的是,当你看几何的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文件?感谢
答案 0 :(得分:2)
具有顶点和法线的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这样没有多重索引的格式。