将MDLMesh分成多个SCNGeometry

Dividing MDLMesh into multiple SCNGeometry

我有一个 .obj 文件,其中包含一个 3D 模型,分为多个较小的网格,例如正面和背面。
我的目标是将此文件加载到 SceneKit 视图中并与模型的不同部分交互,为它们着色、select、隐藏它们或单独移动它们。

我能够将文件加载到 MDLAsset 中,其中包含 MDLMesh,它本身包含所有子网格 MDLSubmesh

要显示加载的模型,我必须将 MDLMesh 转换为 SCNGeometry
基本方法是调用SCNGeometry geometryWithMDLMesh:(MDLMesh *)mdlMesh。这很好用,SCNGeometry 包含不同的 SCNGeometryElements.

但是,在将其转换为 Scene Kit Geometry 时,MDLSubmesh 中的很多信息都丢失了,而且我与不同子网格交互的能力非常有限。

如果我将所有 MDLSubmesh 单独转换为 SCNGeometry 将是理想的。我尝试了两种不同的方法:

  1. 我尝试对每个子网格使用 [MDLMes newSubdividedMesh: aMesh submeshIndex: i subdivisionLevels:0]。然后我用它们创建了 SCNGeometry
    问题是 SceneKit 没有按方面渲染场景。几何体工作正常,但光线未应用于模型,当我转换整个 MDLMesh.
  2. 时工作正常

从每个子网格生成一个新网格:

for (NSInteger i = 0; i < [[mesh submeshes] count]; i++) {
    MDLMesh *submesh = [MDLMesh newSubdividedMesh:mesh submeshIndex:i subdivisionLevels:0];
    SCNGeometry *geometry = [SCNGeometry geometryWithMDLMesh:submesh];           
    SCNNode *subNode = [SCNNode nodeWithGeometry:geometry];          
    [node addChildNode:subNode];
}

使用这种方法生成的渲染结果 rendering with subdivided meshes and when converting the whole MDLMeshrendering the whole mesh。请注意使用上述代码在第一次渲染时缺少灯光效果。

  1. 第二种方法是用SCNGeometry geometryWithSources:elements:方法生成SCNGeometry。虽然我怀疑这是 'right' 的方法,但这是我尝试过的方法。

    • (SCNNode*) loadMDLMesh : (MDLMesh*) mesh withSubmeshes: (bool) sub { 如果(子){ //生成场景工具包节点 SCNNode * 节点 = [SCNNode 节点];

      //Generate a new mesh from each submesh
      for (NSInteger i = 0; i < [[mesh submeshes] count]; i++) {
          //Create the geometry element from the mdl sub mesh 
          SCNGeometryElement *element = [SCNGeometryElement geometryElementWithMDLSubmesh: [[mesh submeshes] objectAtIndex:i] ];
      
          //Create a geometry source from the index buffer
          MDLMeshBufferMap *map = [[[[mesh submeshes] objectAtIndex:i] indexBuffer] map];
      
          SCNGeometrySource *source = [SCNGeometrySource geometrySourceWithVertices:[map bytes] count:[[[mesh submeshes] objectAtIndex:i] indexCount]];
      
          //Create the SCNGeometry from the source and the element
          SCNGeometry *subMesh = [SCNGeometry geometryWithSources:[NSArray arrayWithObject:source] elements:[NSArray arrayWithObject:element]];
      
          //Update the name
          subMesh.name = [[[mesh submeshes] objectAtIndex:i] name];
      
          //Create a subnode and add it to the object node
          SCNNode *subNode = [SCNNode nodeWithGeometry:subMesh];
      
          [node addChildNode:subNode];
      }       
      
      return node;
      
      } else {
      return [SCNNode nodeWithMDLObject:mesh];
      }
      

不幸的是,该应用程序因错误访问异常而崩溃。

如您所见,我在开发 objective-c 方面经验不足。任何帮助解决我的想法或细分网格的不同方法都会很棒。

谢谢。

[Re-posting 评论作为答案,因为它似乎提供了一个有效的解决方案]

我看起来你在使用 +newSubdividedMesh:submeshIndex:subdivisionLevels: 从子网格构建新网格时缺少法线。也许 -initWithVertexBuffer:vertexCount:descriptor:submeshes: 会带来更好的结果?