【问题标题】:Change color of child node改变子节点的颜色
【发布时间】:2015-09-08 17:05:31
【问题描述】:

目前,当我更改子节点的颜色时,它会导致所有其他子节点的颜色发生变化,这是我不想要的。

我这样改变子节点的颜色:

let materials = node.geometry?.materials as! [SCNMaterial]
let material = materials[0]
material.diffuse.contents = UIColor.grayColor()

【问题讨论】:

  • 您是否有机会使用共享几何?这可以解释一个节点上的颜色变化会改变其他节点上的颜色这一事实。您可能想尝试取消共享几何,然后取消共享材质。
  • @sambro 我使用来自github.com/jamesfolk/SceneKitVehicleDemo 的汽车模型。我不知道它是否是共享几何图形。我正在尝试更改轮子的颜色,轮子是此文件中的子节点。

标签: swift ios8 scenekit


【解决方案1】:

默认情况下,如果您有多个节点分配了相同的SCNGeometry 实例,那么这些节点也具有相同的材质。更改材质会更改使用该材质的所有节点的外观。

SCNGeometry 对象并不直接表示几何数据——它实际上只是一组几何数据和一组材料之间关联的轻量级表示。因此,当您想在具有不同材质的多个节点上渲染相同的几何体时,只需复制几何体对象......它们仍将共享基础数据,因此渲染时间成本可以忽略不计,但您将能够更改他们的材料独立。

复制几何后,您可以单独更改两个几何上的材质,但这些组仍共享相同的SCNMaterial 实例。 (这很有用,因为一个几何体可以有多种材质,并且每种材质都是一组属性,因此尽可能共享它们是有效的。)因此,您可以为每个几何体分配新材质,或取消共享材质。

// Using copy as a way to get two nodes with the same material
// (but your scene might already have two such nodes)
let node2 = node1.copy() as! SCNNode 

// Right now, node2 is sharing geometry. This changes the color of both:
node1.geometry?.firstMaterial?.diffuse.contents = UIColor.redColor()

// Un-share the geometry by copying
node2.geometry = node1.geometry!.copy()
// Un-share the material, too
node2.geometry?.firstMaterial = node1.geometry!.firstMaterial!.copy() as? SCNMaterial
// Now, we can change node2's material without changing node1's:
node2.geometry?.firstMaterial?.diffuse.contents = UIColor.blueColor()

Building a Game with SceneKit 的 WWDC 2014 演讲中对此进行了很好的讨论。相关位在视频中大约 37:15 或 PDF 中的幻灯片 159。

【讨论】:

  • 不幸的是,这不起作用。可能是因为 node1 应该被 node2 替换,但我不知道如何。
  • 我有这个确切的代码在操场上工作......你可能想确保你添加到场景中的东西是你的 node1node2重新期待,也许?
  • 澄清一下:你用过car model from github.com/jamesfolk/SceneKitVehicleDemo.的模型吗?我想做的是改变汽车车轮的颜色。
  • 该示例代码最初来自 Apple,顺便说一句 - 请查看 here 以获取原始下载以及 Apple 未来提供的任何更新。
  • 要在那个场景中找到车轮,你有两个问题:首先,你需要抓住正确的节点——不是汽车本身,而是持有车轮几何形状的节点之一(命名为wheelRearR 在场景中)。其次,模型在运输样品中的显示方式,轮胎和车轮内部由于纹理映射而看起来不同,因此您将无法通过分配纯色材料来保持这一点。但是您应该能够抓取其中一个轮子节点,取消其几何形状和材质的共享,并为其指定纯色。
【解决方案2】:

基于@sambro 评论和@rickster 代码,这里是现成的答案:

// Un-share the geometry by copying
node.geometry = node.geometry!.copy() as? SCNGeometry
// Un-share the material, too
node.geometry?.firstMaterial = node.geometry?.firstMaterial!.copy() as? SCNMaterial
// Now, we can change node's material without changing parent and other childs:
node.geometry?.firstMaterial?.diffuse.contents = UIColor.blueColor()

【讨论】:

    【解决方案3】:

    现在已经简化了

        let searchNode = node.childNode(withName: "YOUR_CHILD_NODE_NAME", recursively: true)
        searchNode?.geometry?.firstMaterial?.diffuse.contents = UIColor.red
    

    在这里,它搜索完整的树。子节点,子子节点等等,直到找到具有特定名称的节点。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多