3

我将 COLLADA 文件中的网格加载到 SceneKit 中。假设我有一个立方体,其材质具有一定的纹理。然后在代码中,我想制作这个 SCNNode 的新副本——我clone到目前为止已经使用过——然后我需要设置一个新的纹理。这就是问题所在,因为如果我获得其中一个克隆立方体的命名材质并更新其纹理 ( thematerialofmycube.diffuse.contents = @"somefile.png"),将为立方体的所有实例设置相同的纹理。clone显然不会深度复制几何、材料和纹理之类的东西。所以我尝试的是制作几何体本身的副本,并尝试制作新材质,为新材质设置新纹理,并将该材质添加到新几何体的材质数组中,同时移除旧材质. 似乎没有直接的方法可以这样做(材料被命名,但存在于一个数组中,因此理论上几种材料可以具有相同的名称 - 这会导致从数组中添加/删除一些庞大的对象),以及何时我这样做了,新的纹理出现了,但它们倒置了,而且材料的顺序似乎不正确,因为我用“背面”纹理代替了正面纹理,反之亦然。我希望我不必在我的 3d 编辑器中绘制所有这些东西,

我具体做的是在我的 3d 编辑器中画了一张王牌,并将其导出到 COLLADA。现在我有 52 个 png 的王牌面——显然我需要替换新的王牌实例的面。

4

4 回答 4

1

似乎该阵列中材料的顺序(非常)重要。如果我将具有更新纹理的新材料插入到与我删除的相同的数组索引中,本质上是进行替换,那么纹理会显示在正确的面上并且不会倒置 - 即它们的显示方式与与源 SCNNode。我还没有运行它更长的时间,看看它是否能始终如一地工作。

于 2014-08-11T08:42:21.090 回答
1

[SCNNode 克隆] 这样做是出于效率原因。试试这个代码(如果你想创建一个 SCNNode 类别:

//********************************************************
//<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// SCNNode duplicate
//********************************************************
//<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
- (SCNNode *)duplicateNode:(SCNNode *)node
{
    SCNNode *newNode = [node clone];
    newNode.geometry = [node.geometry copy];
    newNode.geometry.firstMaterial = [node.geometry.firstMaterial copy];

    return newNode;
}
于 2015-10-27T12:09:34.087 回答
1

快速回答:

fileprivate func deepCopyNode(node: SCNNode) -> SCNNode {
    let clone = node.clone()
    clone.geometry = node.geometry?.copy() as? SCNGeometry
    if let g = node.geometry {
        clone.geometry?.materials = g.materials.map{ $0.copy() as! SCNMaterial }
    }
    return clone
}
于 2018-04-06T08:44:26.690 回答
0

很久没问这个问题了。但我想我会提供一个辅助功能:

func deepCopyNode(_ node: SCNNode) -> SCNNode {
  
  // internal function for recurrsive calls
  func deepCopyInternals(_ node: SCNNode) {
    node.geometry = node.geometry?.copy() as? SCNGeometry
    if let g = node.geometry {
      node.geometry?.materials = g.materials.map { $0.copy() as! SCNMaterial }
    }
    for child in node.childNodes {
      deepCopyInternals(child)
    }
  }
  
  // CLONE main node (and all kids)
  // issue here is that both geometry and materials are linked
  // still. In our deepCopyNode we want new copies of everything
  let clone = node.clone()
  
  // we use this internal function to update both
  // geometry and materials, as well as process all children
  // this is the *deep* part of "deepCopy"
  deepCopyInternals(clone)
  
  return clone
}
于 2021-03-14T02:26:11.257 回答