'SCNMaterial not changing color when setting 'diffuse.contents'
I have a bunch of cubes (SCNBox for the geometry of an SCNNode).
The cubes each have a single SCNMaterial (a UIColor) assigned to their respective materials array.
Here's what that looks like:
let box = SCNBox(width: 3.0, height: 3.0, length: 3.0, chamferRadius: 0.2)
let cubeNode = SCNNode(geometry: box)
let material = SCNMaterial()
material.diffuse.contents = UIColor.red
box.materials = [material]
(self.view as! SCNView).scene?.rootNode.addChildNode(cubeNode)
When you tap on one of these cubes, I try to change their color to green by doing the following:
material.diffuse.contents = UIColor.green
But this doesn't always work! Sometimes the cube turns green as desired, and sometimes it stays red.
I've tested some theories, and I've established the following:
- The code that sets the cube's color to green does, indeed, run.
- The material is, indeed, set to green (I inspected
material.diffuse.contentsviaprint()), and I can see that the color was set correctly. - The code that determines which cube was tapped works correctly. So, it's not a matter of hit testing or anything like that.
- The problem happens on both Simulator and device.
For lighting, I'm simply using scnView.autoenablesDefaultLighting = true. No additional lights involved.
Question: Has anyone else experienced this problem? Am I doing something wrong, or is this a legitimate bug?
EDIT: Here's a bit more information about how I'm trying to set the color of the cubes when tapped:
@objc
func handleTap(_ gestureRecognize: UIGestureRecognizer) {
let scnView = self.view as! SCNView
let p = gestureRecognize.location(in: scnView)
let hitResults = scnView.hitTest(p, options: [:])
if hitResults.count > 0 {
let result = hitResults[0]
let material = result.node.geometry?.firstMaterial
if let material = material {
print("GREEN") //Prints "GREEN" every time, as expected -- but sometimes the cube turns green and sometimes it does not.
material.diffuse.contents = UIColor.green
}
}
}
EDIT #2: I've managed to get this working, but I'm left with more questions than answers.
Instead of updating the cubes' color by setting material.diffuse.contents, I tried using material.emission.contents. For whatever reason, this works 100% of the time, as desired.
The downside is that the visual appearance of the cubes when setting material.emission.contents is a bit odd, and not necessarily what I'm looking for. It's green, yes -- but it's different somehow. But that's another matter.
Feel free to post an answer to this question if you can explain these behaviors.
Solution 1:[1]
I tried your sample code in Xcode 13.3 on macOS 12.3.1, everything works fine (app and simulator).
Make sure you're using UITapGestureRecognizer, not UIPanGestureRecognizer:
let recognizer = UITapGestureRecognizer(target: self, action: #selector(tap))
(self.view as! SCNView).addGestureRecognizer(recognizer)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
