I can't get UIBezierPath
's lineWidth
property to work when using it in SceneKit. The end product has the minimum lineWidth (it's very thin), whereas I need a thick line.
The path is used to construct an SCNShape
, which is then used to construct an SCNNode
.
Consider the following code:
let hugePath = UIBezierPath()
hugePath.lineWidth = 40.0 //Has no effect
hugePath.move(to: CGPoint(x: previousPathPosition.x, y: previousPathPosition.y))
hugePath.addLine(to: CGPoint(x: block.position.x, y: block.position.y))
let hugeShape = SCNShape(path: hugePath, extrusionDepth: 150.0)
let hugeMaterial = SCNMaterial()
hugeMaterial.diffuse.contents = UIColor.red
hugeShape.materials = [hugeMaterial, hugeMaterial, hugeMaterial, hugeMaterial, hugeMaterial, hugeMaterial]
let hugeNode = SCNNode(geometry: hugeShape)
hugeNode.position.x = 0.0
hugeNode.position.z = 5.0
hugeNode.position.y = 0.0
scnView.scene?.rootNode.addChildNode(hugeNode)
There are numerous SO questions on how this problem pertains to UIBezierPath
and CAShapeLayer
, but none that I see on how it pertains to SceneKit. With the CAShapeLayer
problem, the
CodePudding user response:
From Apple's docs: "SceneKit uses a right-handed coordinate system where (by default) the direction of view is along the negative z-axis..."
Path geometry starts on the XY plane, and is extruded on the Z-axis.
So, if we start with a (vertical) "line" path and extrude it:
let path = UIBezierPath()
path.move(to: .zero)
path.addLine(to: .init(x: 0.0, y: 1.0))
// extrude it to create the shape
let shape = SCNShape(path: path, extrusionDepth: 10.0)
We get this:
It has Y and Z dimensions, but no X (width).
So, instead of a line, let's start with a rectangle - 0.1 width and 1.0 height:
// rectangle bezier path
let path = UIBezierPath(rect: CGRect(x: 0.0, y: 0.0, width: 0.10, height: 1.0))
We see that the path is on the XY plane... if we extrude it:
// rectangle bezier path
let path = UIBezierPath(rect: CGRect(x: 0.0, y: 0.0, width: 0.10, height: 1.0))
// extrude it to create the shape
let shape = SCNShape(path: path, extrusionDepth: 10.0)
We get this:
Quick example code:
class WallViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let sceneView = SCNView(frame: self.view.frame)
self.view.addSubview(sceneView)
sceneView.allowsCameraControl = true
sceneView.autoenablesDefaultLighting = true
sceneView.backgroundColor = .black
let scene = SCNScene()
sceneView.scene = scene
// rectangle bezier path
let path = UIBezierPath(rect: CGRect(x: 0.0, y: 0.0, width: 0.10, height: 1.0))
// extrude it to create the shape
let shape = SCNShape(path: path, extrusionDepth: 10.0)
let mat = SCNMaterial()
mat.diffuse.contents = UIColor(white: 0.75, alpha: 1.0)
mat.lightingModel = .physicallyBased
shape.materials = [mat]
// set shape node
let shapeNode = SCNNode(geometry: shape)
// add it to the scene
scene.rootNode.addChildNode(shapeNode)
// let's add a camera for the "starting view"
let camera = SCNCamera()
let cameraNode = SCNNode()
cameraNode.camera = camera
cameraNode.position = SCNVector3(x: 0.5, y: 2.0, z: 7.0)
scene.rootNode.addChildNode(cameraNode)
let constraint = SCNLookAtConstraint(target: shapeNode)
constraint.isGimbalLockEnabled = true
cameraNode.constraints = [constraint]
}
}