SCNShape not drawing with UIBezierPath under certain circumstances

痴心易碎 提交于 2019-12-08 11:48:14

问题


I believe this may be an iOS bug, and I've reported it to Apple via Bug Report. I'll post it here in case there's some workaround I can use, or explanation of the cause.

I'm wanting to draw the stroke of a UIBezierPath within SceneKit. I'm using the CGPath copyStrokingWithWidth function, and then creating a SCNShape using the given path.

This works fine for lines with 2 points, but on lines with 3 points, the SCNShape doesn't display anything. I've determined that this is only the case when the lineWidth is more than 0.1. With lineWidth set to 0.1, it displays perfectly.

let strokeBezierPath = UIBezierPath()
strokeBezierPath.lineWidth = 1
strokeBezierPath.move(to: CGPoint.zero)
strokeBezierPath.addLine(to: CGPoint(x: 10, y: 0))
strokeBezierPath.addLine(to: CGPoint(x: 10, y: 10))
let cgPath = strokeBezierPath.cgPath.copy(
    strokingWithWidth: strokeBezierPath.lineWidth,
    lineCap: strokeBezierPath.lineCapStyle,
    lineJoin: strokeBezierPath.lineJoinStyle,
    miterLimit: strokeBezierPath.miterLimit)

let bezierPath = UIBezierPath(cgPath: cgPath)
let shape = SCNShape(path: bezierPath, extrusionDepth: 1)
shape.firstMaterial?.diffuse.contents = UIColor.blue
let node = SCNNode(geometry: shape)
node.position.z = -40

sceneView.scene.rootNode.addChildNode(node)

This works fine with:

  • Just the first 2 points
  • Line width of 0.1
  • A manually-drawn bezier path covering the same area

Printing the UIBezierPath for line width as 0.1 (does display):

<UIBezierPath: 0x1d00b12e0; <MoveTo {0, 0.050000000000000003}>,
 <LineTo {10, 0.050000000000000003}>,
 <LineTo {9.9499999999999993, 10}>,
 <LineTo {10.050000000000001, 10}>,
 <LineTo {10.050000000000001, 0}>,
 <LineTo {0, -0.050000000000000003}>,
 <LineTo {0, 0.050000000000000003}>,
 <Close>

With line width as 0.2 (doesn't display):

<UIBezierPath: 0x1d00b7160; <MoveTo {0, 0.10000000000000001}>,
 <LineTo {10, 0.10000000000000001}>,
 <LineTo {9.9000000000000004, 0}>,
 <LineTo {9.9000000000000004, 10}>,
 <LineTo {10.1, 10}>,
 <LineTo {10.1, 0}>,
 <LineTo {10, -0.10000000000000001}>,
 <LineTo {0, -0.10000000000000001}>,
 <LineTo {0, 0.10000000000000001}>,
 <Close>

回答1:


   let strokeBezierPath = UIBezierPath()
          strokeBezierPath.lineWidth = 1   
          strokeBezierPath.move(to: CGPoint.zero)
          strokeBezierPath.addLine(to: CGPoint(x: 10, y: 0))
          strokeBezierPath.addLine(to: CGPoint(x: 10, y: 10))

You haven’t closed the path. You won’t be able to extrude two line segments that have not been closed... so nothing will appear. Close the path off with the following. This will bring up your geometry in the sceneView.

    strokeBezierPath.close()

Edit: Scenekit units are in metres. So to work with a smaller object in front of you. Change your units, and linewidth to the following. This will put the object 1 metre in front... and much smaller so you can see whats going on better.

let strokeBezierPath = UIBezierPath()
    strokeBezierPath.lineWidth = 0.01
    strokeBezierPath.move(to: CGPoint.zero)
    strokeBezierPath.addLine(to: CGPoint(x: 0.1, y: 0))
    strokeBezierPath.addLine(to: CGPoint(x: 0.1, y: 0.1))
    strokeBezierPath.addLine(to: CGPoint(x: 0.0, y: 0.1))
    strokeBezierPath.addLine(to: CGPoint(x: 0, y: 0))
    strokeBezierPath.close()
    let cgPath = strokeBezierPath.cgPath.copy(
        strokingWithWidth: strokeBezierPath.lineWidth,
        lineCap: strokeBezierPath.lineCapStyle,
        lineJoin: strokeBezierPath.lineJoinStyle,
        miterLimit: strokeBezierPath.miterLimit)

    let bezierPath = UIBezierPath(cgPath: cgPath)
    let shape = SCNShape(path: bezierPath, extrusionDepth: 0.01)
    shape.firstMaterial?.diffuse.contents = UIColor.blue
    let node = SCNNode(geometry: shape)
    node.position.z = -1

    sceneView.scene.rootNode.addChildNode(node)


来源:https://stackoverflow.com/questions/48628243/scnshape-not-drawing-with-uibezierpath-under-certain-circumstances

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!