将MDLMesh划分为多个SCNGeometry

时间:2016-01-20 10:39:56

标签: objective-c swift scenekit

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

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

要显示已加载的模型,我必须将MDLMesh转换为SCNGeometry 基本方法是致电SCNGeometry geometryWithMDLMesh:(MDLMesh *)mdlMesh。这工作正常,SCNGeometry包含不同的SCNGeometryElements

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

如果我将所有SCNGeometry单独转换为[MDLMes newSubdividedMesh: aMesh submeshIndex: i subdivisionLevels:0],那将是理想的选择。我尝试了两种不同的方法:

  1. 我尝试为每个子网格使用SCNGeometry。然后我用它们创建了MDLMesh 问题是SceneKit没有将场景渲染为预期。几何图形正在工作,但光线未应用于模型,这在我转换整个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]; } 时起作用。
  2. 从每个子网格生成一个新网格:

    MDLMesh

    使用此方法rendering with subdivided meshes生成的渲染以及转换整个SCNGeometry rendering the whole mesh时的渲染。请注意使用上述代码对第一次渲染缺少光照效果。

    1. 第二种方法是使用SCNGeometry geometryWithSources:elements:方法生成//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]; } 。虽然我怀疑这是“正确”的做法,但这就是我尝试过的。

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

        signedint = \s*[+-]?\s*[0-9]+\s*
        
    2. 不幸的是,该应用程序崩溃时出现了错误访问异常。

      正如人们所看到的,我不具备开发Objective-c的经验。任何帮助修复我的想法或不同的细分网格的方法都会很棒。

      谢谢。

1 个答案:

答案 0 :(得分:1)

[重新发布评论作为答案,因为它似乎提供了一个有效的解决方案]

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