Swift 在SceneKit中绘制三维圆弧和螺旋线

Swift 在SceneKit中绘制三维圆弧和螺旋线,swift,scenekit,Swift,Scenekit,最近的一个问题让我再次想起了SceneKit,我想起了一个我从未解决过的问题 我的应用程序使用SK显示天线设计。大多数天线使用金属棒和网状反射器,所以我使用SCN圆柱作为天线棒,SCN平面作为反射器,SCN地板作为地面。整个过程花了几个小时,我完全不懂3D 但有些天线使用弯曲成圆弧或螺旋的电线,我在这里用几个圆柱端对端地做了一些蹩脚的分段物体。看起来很好吃 理想情况下,我想一个单一的对象,渲染一个圆柱截面的弧或螺旋。基本上是斯坎特罗斯,但有一个开始和结束的角度。谈到在SK中使用UIBezierP

最近的一个问题让我再次想起了SceneKit,我想起了一个我从未解决过的问题

我的应用程序使用SK显示天线设计。大多数天线使用金属棒和网状反射器,所以我使用SCN圆柱作为天线棒,SCN平面作为反射器,SCN地板作为地面。整个过程花了几个小时,我完全不懂3D

但有些天线使用弯曲成圆弧或螺旋的电线,我在这里用几个圆柱端对端地做了一些蹩脚的分段物体。看起来很好吃

理想情况下,我想一个单一的对象,渲染一个圆柱截面的弧或螺旋。基本上是斯坎特罗斯,但有一个开始和结束的角度。谈到在SK中使用UIBezierPath,但它使用
extrupt
生成带状形状。有没有一种方法可以做一些类似的事情,但是要有一个圆柱体的横截面(比如一个部分的圆锥形)


我知道我可以通过创建顶点(和法线等)来创建自定义形状,但我希望我错过了一个更简单的解决方案。

以下是一些可能会有所帮助的起点

一种方法是使用更多的圆柱体,使其更短。这与SCNGeometry原语的各种
segmentCount
属性背后的想法相同。我们能看到当前链接圆柱体版本的屏幕截图吗

如果增加
高度分段计数
,可以使用此处概述的方法:


我只是看了一下SCNShape。我想您可以使用着色器修改器将挤出的形状扭曲为圆形横截面。但是SCNShape似乎没有公开段计数属性,我认为您需要创建足够的拉伸段以获得良好的外观。
chamferRadius
chamferRadius
属性看起来很有趣。我想知道您是否可以使用这些来创建一个看起来不错的拉伸。

您可以使用
SCNShape
完成的圆弧。从我的另一个答案中的技术开始,得到一个拉伸的带状弧线。您需要确保路径追溯到自身的部分偏移的距离与拉伸深度相同,因此最终得到的形状横截面为正方形

要使其横截面为圆形,请使用属性-为其指定四分之一圆的路径,并将倒角半径设置为挤出深度的一半,四个四分之一圆倒角将相交,形成圆形横截面

螺旋线是另一个故事
SCNShape
采用平面路径(仅在二维中变化)并将其挤出以生成三维实体。螺旋线是一条从三维开始变化的路径。SceneKit没有任何东西可以用这样的术语描述形状,所以这里没有超简单的答案

HalMueller提到的着色器修改器解决方案很有趣,但存在问题。在几何体入口点使用修改器进行简单的弯曲很简单,例如,将每个y坐标偏移一定量,甚至偏移量也是原因的函数。但这是一个一维变换,所以你不能用它来缠绕导线。(它也会改变横截面。)最重要的是,着色器修改器在渲染时出现在GPU上,因此它们的效果是一种错觉:SceneKit模型中的“真实”几何体仍然是圆柱体,因此命中测试等功能适用于该几何体,而不适用于变换的几何体


制作类似螺旋的东西的最佳解决方案可能是自定义几何体—生成自己的顶点数据(
SCNGeometrySource
)。如果你遵循螺旋线的形状,那么找到螺旋线上的点集的数学非常简单。若要围绕其包裹横截面,请按照创建螺旋上每个点的局部坐标系。然后制作一个索引缓冲区(
SCNGeometryElement
),将所有这些点缝合到一个带有三角形或三边三角形的曲面中。(好吧,这是一个很深的话题,但是完整的教程对于一个非常好的答案来说太大了。不过,这应该足够作为一个面包屑开始了……

最优秀的答案。关于命中测试的这一点特别有趣,这是我从未考虑过的。