将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
将是理想的。我尝试了两种不同的方法:
- 我尝试对每个子网格使用
[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 and when converting the whole MDLMesh
rendering the whole mesh。请注意使用上述代码在第一次渲染时缺少灯光效果。
第二种方法是用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:
会带来更好的结果?
我有一个 .obj 文件,其中包含一个 3D 模型,分为多个较小的网格,例如正面和背面。
我的目标是将此文件加载到 SceneKit 视图中并与模型的不同部分交互,为它们着色、select、隐藏它们或单独移动它们。
我能够将文件加载到 MDLAsset
中,其中包含 MDLMesh
,它本身包含所有子网格 MDLSubmesh
。
要显示加载的模型,我必须将 MDLMesh
转换为 SCNGeometry
。
基本方法是调用SCNGeometry geometryWithMDLMesh:(MDLMesh *)mdlMesh
。这很好用,SCNGeometry
包含不同的 SCNGeometryElements
.
但是,在将其转换为 Scene Kit Geometry 时,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 and when converting the whole MDLMesh
rendering the whole mesh。请注意使用上述代码在第一次渲染时缺少灯光效果。
第二种方法是用
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:
会带来更好的结果?