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

查看:150
本文介绍了带有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日,我收到了回复,要求提供示例代码和资产,两天后提供了该示例。此后,我没有收到任何回复(希望是因为他们正忙于从假期赶上来...)。

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选项无法正常工作。为了从Model 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天全站免登陆