带有 ModelIO 的混合拓扑(四/三) [英] Mixed topology (quad/tri) with ModelIO

查看:17
本文介绍了带有 ModelIO 的混合拓扑(四/三)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm importing some simple OBJ assets using ModelIO like so:

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

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

... and then adding them to a SceneKit SCN file. But, whenever I have meshes that have both quads/tris (often the case, for example eyeball meshes), the resulting mesh is jumbled:

不正确的网状拓扑

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

Re-topologizing isn't a good option since I sometimes have low-poly meshes with very specific topology, so I can't just set preserveTopology to false... I need a result with variable topology (i.e. MDLGeometryType.variableTopology).

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

How do I import these files correctly preserving their original topology?

推荐答案

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

I reported this as a bug at Apple Bug Reporter on 25th of November, bug id: 35687088

总结:SCNSceneSourceLoadingOptionPreserveOriginalTopology 实际上并不保留原始拓扑.相反,它将几何图形转换为所有四边形,从而严重破坏了 3D 模型.根据其名称,它的行为应该与 Model IO 资产加载的 preserveTopology 完全一样.

Summary: SCNSceneSourceLoadingOptionPreserveOriginalTopology does not actually preserve the original topology. Instead, it converts the geometry to all quads, messing up the 3D model badly. Based on its name it should behave exactly like preserveTopology of Model IO asset loading.

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

Steps to Reproduce: Load an OBJ file that has both triangles and polygons using SCNSceneSourceLoadingOptionPreserveOriginalTopology and load the same file into an MDLMesh using preserveTopology of ModelIO. Notice how it only works properly for the latter. Even when you create a new SCNGeometry based on the MDLMesh, it will "quadify" the mesh again to contain only quads (while it should support 3-gons and up).

12 月 13 日,我收到了一份回复,要求提供示例代码和资产,我在 2 天后提供了该请求.从那以后我就没有收到回复(希望是因为他们正忙于赶上假期......).

On December 13th I received a reply with a request for sample code and assets, which I supplied 2 days later. I have not received a reply since (hopefully because they are just busy from catching up from the holiday season...).

正如我在我的错误报告摘要中提到的,使用模型 I/O 加载资产确实可以正常工作,但是当您基于该 MDLMesh 创建 SCNNode 时,它​​最终会再次弄乱几何图形.

As I mentioned in my bug report's summary, loading the asset with Model I/O does work properly, but then when you create a SCNNode based on that MDLMesh it ends up messing up the geometry again.

在我的情况下,我加载的 OBJ 文件具有已知格式,因为它们总是也与我的应用程序一起导出的文件(无法线、颜色、UV).所以我要做的是手动将 MDLMesh(缓冲区、面拓扑等)的信息加载到数组中,然后我从中手动创建 SCNGeometry.我没有一个完整的单独的代码给你,因为它有很多并且混合了很多特定于我的应用程序的代码,它在目标 C 中.但为了说明:

In my case the OBJ files I load have a known format as they are always files also exported with my app (no normals, colors, UV). So what I do is load the information of the MDLMesh (buffers, facetopology etc) manually into arrays, from which I then create a SCNGeometry manually. I don't have a complete separate piece of code of that for you as it is a lot and mixed with a lot of code specific to my app, and it's in Objective C. But to illustrate:

    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 选项无法正常工作.为了从模型 I/O 中的工作版本到 SceneKit,我基本上必须编写自己的转换器.

In short, the preserveTopology option in SceneKit isn't working properly. To get from the working version in Model I/O to SceneKit I basically had to write my own converter.

这篇关于带有 ModelIO 的混合拓扑(四/三)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆