使用ModelIO的混合拓扑(quad / tri)
我正在使用ModelIO导入一些简单的OBJ资产,如下所示:
let mdlAsset = MDLAsset(url: url, vertexDescriptor: nil, bufferAllocator: nil, preserveTopology: true, error: nil)
…然后将它们添加到SceneKit SCN文件中。 但是,每当我的网格都有四边形/三边形(通常情况下,例如眼球网格)时,生成的网格就会混乱:
网格拓扑不正确
重新拓扑不是一个好选择,因为我有时会使用具有非常特定拓扑的低多边形网格,因此我不能将preserveTopology设置为false …我需要一个具有可变拓扑的结果(即MDLGeometryType.variableTopology)。
如何正确导入这些文件以保留其原始拓扑?
我在11月25日将此错误报告给了Apple Bug Reporter,错误ID:35687088
简介:SCNSceneSourceLoadingOptionPreserveOriginalTopology实际上不保留原始拓扑。 相反,它将几何转换为所有四边形,严重搞乱3D模型。 根据其名称,它应该与模型IO资产加载的preserveTopology完全相同。
重现步骤:使用SCNSceneSourceLoadingOptionPreserveOriginalTopology加载包含三角形和多边形的OBJ文件,并使用ModelIO的preserveTopology将相同的文件加载到MDLMesh中。 注意它只对后者有效。 即使您基于MDLMesh创建新的SCNGeometry,它也会再次“网格化”网格以仅包含四边形(同时它应该支持3-gons以上)。
12月13日,我收到了一份回复,其中提供了样本代码和资产的请求,我在2天后提供了该请求。 我没有收到回复(希望因为他们只是忙着从节日季节赶上来……)。
正如我在错误报告的摘要中提到的那样,使用模型I / O加载资产确实可以正常工作,但是当您基于该MDLMesh创建SCNNode时,它最终会再次弄乱几何体。
在我的情况下,我加载的OBJ文件具有已知的格式,因为它们总是随我的应用程序导出的文件(没有法线,颜色,UV)。 所以我所做的是手动将MDLMesh(缓冲区,面板拓扑等)的信息加载到数组中,然后从中手动创建SCNGeometry。 我没有完整的单独代码,因为它很多,并且混合了很多特定于我的应用程序的代码,并且它在Objective C中。但是为了说明:
NSError *scnsrcError; MDLAsset *asset = [[MDLAsset alloc] initWithURL:objURL vertexDescriptor:nil bufferAllocator:nil preserveTopology:YES error:&scnsrcError]; NSLog(@"%@", scnsrcError.localizedDescription); MDLMesh * newMesh = (MDLMesh *)[asset objectAtIndex:0]; for (MDLSubmesh *faces in newMesh.submeshes) { //MDLSubmesh *faces = newMesh.submeshes.firstObject; MDLMeshBufferData *topo = faces.topology.faceTopology; MDLMeshBufferData *vertIx = faces.indexBuffer; MDLMeshBufferData *verts = newMesh.vertexBuffers.firstObject; int faceCount = (int)faces.topology.faceCount; int8_t *faceIndexValues = malloc(faceCount * sizeof(int8_t)); memcpy(faceIndexValues, topo.data.bytes, faceCount * sizeof(int8_t)); int32_t *vertIndexValues = malloc(faces.indexCount * sizeof(int32_t)); memcpy(vertIndexValues, vertIx.data.bytes, faces.indexCount * sizeof(int32_t)); SCNVector3 *vertValues = malloc(newMesh.vertexCount * sizeof(SCNVector3)); memcpy(vertValues, verts.data.bytes, newMesh.vertexCount * sizeof(SCNVector3)); .... .... }
简而言之,SceneKit中的preserveTopology选项无法正常工作。 要从Model I / O中的工作版本到SceneKit,我基本上必须编写自己的转换器。