具有 ModelIO 的混合拓扑(四路/三路)

2023-12-24

我正在使用 ModelIO 导入一些简单的 OBJ 资源,如下所示:

let mdlAsset = MDLAsset(url: url, vertexDescriptor: nil, bufferAllocator: nil, preserveTopology: true, error: nil)

...然后将它们添加到 SceneKit SCN 文件中。但是,每当我的网格同时具有四边形/三边形(通常是这种情况,例如眼球网格)时,生成的网格就会变得混乱:

网状拓扑不正确 https://i.stack.imgur.com/A7d5z.png

重新拓扑不是一个好的选择,因为我有时会有具有非常特定拓扑的低多边形网格,所以我不能只将preserveTopology设置为false...我需要具有可变拓扑的结果(即MDLGeometryType.variableTopology)。

如何正确导入这些文件并保留其原始拓扑?


我于 11 月 25 日在 Apple Bug Reporter 上报告了此错误,错误 ID:35687088

摘要:SCNSceneSourceLoadingOptionPreserveOriginalTopology 实际上并不保留原始拓扑。相反,它将几何体转换为所有四边形,严重扰乱了 3D 模型。根据其名称,它的行为应该与 Model IO 资产加载的preserveTopology 完全相同。

重现步骤:使用 SCNSceneSourceLoadingOptionPreserveOriginalTopology 加载同时具有三角形和多边形的 OBJ 文件,并使用 ModelIO 的preserveTopology 将同一文件加载到 MDLMesh 中。请注意它如何仅适用于后者。即使您基于 MDLMesh 创建新的 SCNGeometry,它也会再次“限定”网格以仅包含四边形(同时它应该支持 3 边形及以上)。

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,我基本上必须编写自己的转换器。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

具有 ModelIO 的混合拓扑(四路/三路) 的相关文章

随机推荐