I have a series of UIBezierPath
's that I've turned into 3D objects in SceneKit. They form a long, jagged line with occasional gaps (a gap separates one object from another).
The problem: As I move the camera around, the material on the side of the objects flickers strangely and changes colors.
I believe what's happening is that my path-drawing code is wrong, and is somehow creating duplicate objects positioned inside the existing object(s). So, I think the flickering color is really the other, duplicate object showing through.
Here's what the flickering color showing through looks like:
To see the problem in action, the following code can be pasted directly into a new Game
template Xcode project using SceneKit
. You may paste it at the end of GameViewController
's viewDidLoad
.
var previousBezierPathPoint: CGPoint = CGPoint.zero
let numOfPointsPerLine: Int = 8
var hugePath = UIBezierPath()
var wasGap: Bool = false
let gapWidth: CGFloat = 10.0
var currentZdepth: CGFloat = CGFloat.random(in: 5.0...30.0)
for i in 0..<14 {
let pp = wasGap ? CGPoint(x: CGFloat(previousBezierPathPoint.x) gapWidth, y: CGFloat(previousBezierPathPoint.y)) : CGPoint(x: CGFloat(previousBezierPathPoint.x), y: CGFloat(previousBezierPathPoint.y))
let isGap: Bool = i > 1 && Float.random(in: 0...100) > 60.0
if !isGap {
if wasGap || i == 0 {
hugePath = UIBezierPath()
hugePath.move(to: pp)
currentZdepth = CGFloat.random(in: 5.0...30.0)
}
for j in 1..<numOfPointsPerLine {
let point = CGPoint(x: pp.x (CGFloat(j)*25.0), y: pp.y CGFloat.random(in: -8.0...8.0))
hugePath.addLine(to: point)
previousBezierPathPoint = point
}
let pathRef = hugePath.cgPath.copy(strokingWithWidth: 10.0, lineCap: CGLineCap.butt, lineJoin: CGLineJoin.miter, miterLimit: 1.0)
let newPath = UIBezierPath(cgPath: pathRef.normalized())
let hugeShape = SCNShape(path: newPath, extrusionDepth: currentZdepth)
let colors = [
UIColor.green,
UIColor.yellow,
UIColor.purple,
UIColor.gray,
UIColor.darkGray
]
let tempMat = SCNMaterial()
tempMat.diffuse.contents = colors[Int.random(in: 0..<colors.count)]
let frontMat = SCNMaterial()
frontMat.diffuse.contents = UIColor.red
hugeShape.materials = [frontMat, tempMat, tempMat, tempMat, tempMat, tempMat]
let hugeNode = SCNNode()
hugeNode.geometry = hugeShape
hugeNode.position.x = 0.0
hugeNode.position.z = Float(-50.0 (currentZdepth*0.5))
hugeNode.position.y = 0.0
scnView.scene?.rootNode.addChildNode(hugeNode)
} else {
if hugePath.isEmpty == false {
hugePath.close()
}
}
wasGap = isGap
}
Please note that this question is related to this one.
Question: How can I change my code so that there are no duplicate objects?
CodePudding user response:
It looks like you are continually building your path each time through the loop...
Not entirely sure if this will give you your desired results, but...
Instead of this:
if wasGap || i == 0 {
hugePath = UIBezierPath()
hugePath.move(to: pp)
currentZdepth = CGFloat.random(in: 5.0...30.0)
}
try this:
hugePath = UIBezierPath()
hugePath.move(to: pp)
if wasGap || i == 0 {
currentZdepth = CGFloat.random(in: 5.0...30.0)
}