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

查看:104
本文介绍了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天全站免登陆