我有一个 .obj 文件,其中包含 3D 模型,分为多个较小的网格,例如正面和背面。
我的目标是将此文件加载到 SceneKit View 中并与模型的不同部分进行交互,为它们着色、选择它们、隐藏它们或单独移动它们。
我能够将文件加载到 MDLAsset
中,其中包含 MDLMesh
,它本身包含所有子网格作为 MDLSubmesh
。
要显示加载的模型,我必须将 MDLMesh
转换为 SCNGeometry
。
基本方法是调用 SCNGeometry GeometryWithMDLMesh:(MDLMesh *)mdlMesh
。这工作正常,SCNGeometry
包含不同的SCNGeometryElements
。
但是,当将其转换为场景套件几何体时,MDLSubmesh
中的许多信息都会丢失,并且我与不同子网格体交互的能力非常有限。
如果我将所有 MDLSubmesh
单独转换为 SCNGeometry
,那就太理想了。我尝试了两种不同的方法:
- 我尝试对每个子网格体使用
[MDLMes newSubdividedMesh: aMesh submeshIndex: i subdivisionLevels:0]
。然后我用它们创建了SCNGeometry
。
问题是 SceneKit 没有按方面渲染场景。几何体正常工作,但光线未应用于模型,这在我转换整个MDLMesh
时有效。
从每个子网格生成一个新的网格:
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当转换整个 MDLMesh
rendering the whole mesh 时。请注意使用上述代码进行第一次渲染时缺少的灯光效果。
第二种方法是使用
SCNGeometry GeometryWithSources:elements:
方法生成SCNGeometry
。尽管我怀疑这是“正确”的方法,但这就是我尝试过的方法。(SCNNode*) loadMDLMesh : (MDLMesh*) 网格与Submeshes: (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 方面没有那么丰富的经验。任何有助于修正我的想法或分割网格的不同方法的帮助都会很棒。
谢谢。
最佳答案
[重新发布评论作为答案,因为它似乎提供了一个可行的解决方案]
我看起来你在使用 +newSubdividedMesh:submeshIndex:subdivisionLevels:
时缺少法线从子网格构建新的网格。也许-initWithVertexBuffer:vertexCount:descriptor:submeshes:
会带来更好的结果吗?
关于objective-c - 将MDLMesh划分为多个SCNGeometry,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34897721/