SCNShape 在某些情况下不使用 UIBezierPath 绘制 [英] SCNShape not drawing with UIBezierPath under certain circumstances

查看:36
本文介绍了SCNShape 在某些情况下不使用 UIBezierPath 绘制的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我认为这可能是一个 iOS 错误,我已通过错误报告将其报告给 Apple.如果我可以使用一些解决方法或解释原因,我会在此处发布它.

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.

我想在 SceneKit 中绘制 UIBezierPath 的描边.我正在使用 CGPath copyStrokingWithWidth 函数,然后使用给定的路径创建一个 SCNShape.

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.

这适用于 2 点的线,但在 3 点的线上,SCNShape 不显示任何内容.我已经确定只有 lineWidth 大于 0.1 时才会出现这种情况.lineWidth 设置为 0.1,显示完美.

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)

这适用于:

  • 仅前 2 分
  • 0.1 的线宽
  • 手动绘制的覆盖同一区域的贝塞尔曲线

将线宽的 UIBezierPath 打印为 0.1(确实显示):

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>

线宽为0.2(不显示):

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>

推荐答案

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

你还没有关闭路径.您将无法挤出两条尚未闭合的线段……因此不会出现任何内容.使用以下命令关闭路径.这将在 SceneView 中显示您的几何图形.

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

Scenekit 单位以米为单位.所以要处理你面前的一个较小的物体.将您的单位和线宽更改为以下内容.这会将物体放在前面 1 米处……而且小得多,这样您就可以更好地看到正在发生的事情.

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)

这篇关于SCNShape 在某些情况下不使用 UIBezierPath 绘制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆