问题描述
最近这里的一个问题让我再次想到了 SceneKit,我想起了一个我从未解决过的问题.
A recent question here made me think of SceneKit again, and I remembered a problem I never solved.
我的应用使用 SK 显示天线设计.大多数天线使用金属棒和网状反射器,所以我用 SCNCylinder 做棒,SCNPlane 做反射器,SCNFloor 做地面.整个过程花了几个小时,我完全 3D 菜鸟.
My app displays antenna designs using SK. Most antennas use metal rods and mesh reflectors so I used SCNCylinder for the rods, SCNPlane for the reflector and SCNFloor for the ground. The whole thing took a couple of hours, and I'm utterly noob at 3D.
但是有些天线使用弯曲成弧形或螺旋形的电线,我在这里下注并使用多个圆柱体端对端地制作了糟糕的分段对象.它看起来棒极了.
But some antennas use wires bent into arcs or helixes, and I punted here and made crappy segmented objects using several cylinders end-to-end. It looks ass-tastic.
理想情况下,我想要一个单独的对象,它可以渲染具有圆柱形横截面的圆弧或螺旋线.基本上是 SCNTorus,但有一个开始和结束的角度.这篇文章讨论在 SK 中使用 UIBezierPath,但它使用 extrude
产生带状形状.有没有办法做类似的事情,但使用圆柱横截面(如部分 SCNTorus)?
Ideally I would like a single object that renders the arc or helix with a cylindrical cross section. Basically SCNTorus, but with a start and end angle. This post talks about using a UIBezierPath in SK, but it uses extrude
to produce a ribbon-like shape. Is there a way to do something similar but with a cylinder cross section (like a partial SCNTorus)?
我知道我可以通过创建顶点(和法线等)来制作自定义形状,但我希望我错过了一个更简单的解决方案.
I know I can make a custom shape by creating the vertexes (and normals and such) but I'm hoping I missed a simpler solution.
推荐答案
你可以用 SCNShape
做的弧线.从我的其他答案中的技术开始,以获得挤压的带状弧.您需要确保路径追溯到其自身的部分偏移与挤出深度相同的距离,以便最终得到横截面为方形的形状.
An arc you can do with SCNShape
. Start with the technique from my other answer to get an extruded, ribbon-like arc. You'll want to make sure that the part where your path traces back on itself is offset by a distance the same as your extrusion depth, so you end up with a shape that's square in cross section.
要使其横截面呈圆形,请使用 chamferProfile
属性——给它一个四分之一圆的路径,并将倒角半径设置为挤压深度的一半,四个四分之一圆倒角将相交,形成一个圆形横截面.
To make it circular in cross section, use the chamferProfile
property — give it a path that's a quarter circle, and set the chamfer radius equal to half the extrusion depth, and the four quarter-circle chamfers will meet, forming a circular cross section.
螺旋线是另一回事.SCNShape
取一个平面路径——一个仅在二维上变化的路径——并将其挤出以形成一个三维实体.螺旋线是从三个维度开始变化的路径.SceneKit 没有任何以此类方式描述形状的内容,因此这里没有超级简单的答案.
A helix is another story. SCNShape
takes a planar path — one that varies in only two dimensions — and extrudes it to make a three-dimensional solid. A helix is a path that varies in three dimensions to start with. SceneKit doesn't have anything that describes a shape in such terms, so there's no super simple answer here.
@HalMueller 提到的着色器修改器解决方案很有趣,但有问题.在几何入口点使用修改器进行简单的弯曲很简单 - 例如,将每个 y 坐标偏移一定量,甚至偏移量是原因的函数.但这是一个一维变换,所以你不能用它来缠绕电线.(它还改变了横截面.)最重要的是,着色器修改器在渲染时发生在 GPU 上,因此它们的效果是一种错觉:真实"的SceneKit 模型中的几何图形仍然是一个圆柱体,因此诸如命中测试之类的功能适用于该圆柱体,而不适用于转换后的几何图形.
The shader modifier solution @HalMueller alludes to is interesting, but problematic. It's simple to use a modifier at the geometry entry point to make a simple bend — say, offset every y coordinate by some amount, even by an amount that's a function of why. But that's a one-dimensional transform, so you can't use it to wrap a wire around on itself. (It also changes the cross section.) And on top of that, shader modifiers happen on the GPU at render time, so their effects are an illusion: the "real" geometry in SceneKit's model is still a cylinder, so features like hit testing apply to that and not to the transformed geometry.
制作类似螺旋线的最佳解决方案可能是自定义几何体 — 生成您自己的顶点数据 (SCNGeometrySource
).如果您遵循该形状的定义,则查找螺旋上的点集的数学方法非常简单.要在其周围环绕横截面,请按照 Frenet 公式创建螺旋上每个点的局部坐标系.然后创建一个索引缓冲区 (SCNGeometryElement
) 将所有这些点缝合到一个带有三角形或三条带的表面上.(好吧,这是围绕一个深层次的话题挥手的很多手,但完整的教程对于 SO 答案来说太大了.不过,这应该足以作为开始的面包屑......)
The best solution to making something like a helix is probably custom geometry — generating your own vertex data (SCNGeometrySource
). The math for finding the set of points on a helix is pretty simple if you follow that shape's definition. To wrap a cross section around it, follow the Frenet formulas to create a local coordinate frame at each point on the helix. Then make an index buffer (SCNGeometryElement
) to stitch all those points into a surface with triangles or tristrips. (Okay, that's a lot of hand-waving around a deep topic, but a full tutorial is too big for an SO answer. This should be enough of a breadcrumb to get started, though...)
这篇关于在 SceneKit 中绘制 3D 弧线和螺旋线的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!