我有一个包含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]
,那将是理想的选择。我尝试了两种不同的方法:
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];
}
时起作用。从每个子网格生成一个新网格:
MDLMesh
使用此方法rendering with subdivided meshes生成的渲染以及转换整个SCNGeometry
rendering the whole mesh时的渲染。请注意使用上述代码对第一次渲染缺少光照效果。
第二种方法是使用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*
不幸的是,该应用程序崩溃时出现了错误访问异常。
正如人们所看到的,我不具备开发Objective-c的经验。任何帮助修复我的想法或不同的细分网格的方法都会很棒。
谢谢。
答案 0 :(得分:1)
[重新发布评论作为答案,因为它似乎提供了一个有效的解决方案]
当使用+newSubdividedMesh:submeshIndex:subdivisionLevels:
从子网格构建新网格时,我看起来你错过了法线。也许-initWithVertexBuffer:vertexCount:descriptor:submeshes:
会带来更好的结果?