Change color of child node

7k Views Asked by At

Currently when I change child's node color it will led to color change of all another child nodes, which I don't want.

I change color of the child node this way:

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

There are 3 best solutions below

0
On BEST ANSWER

Based on @sambro comment and @rickster code, here is the ready answer:

// 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()
6
On

By default, if you have multiple nodes that have the same SCNGeometry instance assigned to them, then those nodes also have the same materials. Changing a material changes the appearance of all nodes using that material.

An SCNGeometry object doesn't directly represent geometry data — it's actually just a lightweight representation of the association between a set of geometry data and a set of materials. So, when you want to render the same geometry on multiple nodes with different materials, just copy the geometry object... they'll still share the underlying data, so there's negligible render-time cost, but you'll be able to change their materials independently.

After you copy the geometry, you can change the sets of materials on the two geometries independently, but those sets are still sharing the same SCNMaterial instances. (This is useful because a geometry can have multiple materials, and each material is a set of several properties, so it's efficient to share them wherever possible.) So you can either assign new materials to each geometry, or un-share the materials.

// 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()

There's a good discussion of this in the WWDC 2014 talk on Building a Game with SceneKit. The relevant bit is at about 37:15 in the video or slide 159 in the PDF.

0
On

It has been simplified now

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

Here, it searches the complete tree. Child node, sub child node and so on till it finds a node with the specific name.