如何使用Swift在SceneKit中程序化绘制半球体?
问题原因:你误解了SCNShape的作用
你的代码里用UIBezierPath(ovalIn:)创建了一个椭圆,然后通过SCNShape的extrusionDepth把它拉伸成了一个扁的椭圆柱——这是因为SCNShape的核心是把2D路径沿着垂直平面的方向"挤压"成棱柱体,而不是把路径绕轴旋转成回转体(比如半球这种)。所以自然得不到你想要的半球效果。
两种简单的解决方案
方案1:用SCNLatheGeometry(推荐,最直接生成半球)
SCNLatheGeometry专门用来把2D路径绕指定轴旋转成3D回转体,刚好适合做半球。你只需要创建一个半圆的贝塞尔路径,让它绕Y轴旋转即可:
// 1. 创建半圆的贝塞尔路径(半径0.2,对应你原来椭圆的半宽/半高) let halfCirclePath = UIBezierPath() halfCirclePath.addArc( withCenter: CGPoint(x: 0, y: 0), radius: 0.2, startAngle: .pi, // 从π弧度(180度)开始 endAngle: 0, // 到0弧度(0度)结束 clockwise: false // 逆时针绘制,得到上半圆 ) // 闭合路径,确保Lathe能生成完整的几何体 halfCirclePath.addLine(to: CGPoint(x: 0, y: 0)) halfCirclePath.close() // 2. 用半圆路径生成半球几何体 let hemisphereGeometry = SCNLatheGeometry(path: halfCirclePath) // 调整径向分段数,数值越高半球表面越平滑(默认是16,这里设32更细腻) hemisphereGeometry.radialSegmentCount = 32 // 3. 创建节点并添加到场景 let hemisphereNode = SCNNode(geometry: hemisphereGeometry) // 如果你需要调整位置/旋转,直接修改节点属性即可 // hemisphereNode.position = SCNVector3(0, 0.1, 0) scene.rootNode.addChildNode(hemisphereNode)
方案2:用SCNSphere裁剪出半球
如果你更习惯用球体,也可以先创建完整球体,再通过裁剪平面只保留上半部分:
// 1. 创建完整球体(半径0.2,和方案1一致) let sphere = SCNSphere(radius: 0.2) sphere.segmentCount = 32 // 保证表面平滑 // 2. 创建裁剪平面:剔除Y轴负方向的部分 let clipPlane = SCNClipPlane() clipPlane.plane = SCNPlane(width: 0.5, height: 0.5) clipPlane.plane.firstMaterial?.diffuse.contents = UIColor.clear // 裁剪平面透明 clipPlane.position = SCNVector3(0, 0, 0) // 裁剪平面位于原点 clipPlane.normal = SCNVector3(0, -1, 0) // 法线向下,只保留法线另一侧(Y正方向)的部分 // 3. 创建球体节点并启用裁剪 let hemisphereNode = SCNNode(geometry: sphere) hemisphereNode.clipsToPlanes = true hemisphereNode.clipPlanes = [clipPlane] scene.rootNode.addChildNode(hemisphereNode)
额外提示
如果非要用SCNShape实现,其实并不合适——它的设计初衷是生成棱柱类的3D模型,而非曲面回转体。强行用它做半球需要复杂的路径组合和节点变换,效果还不如上面两种方案自然。
内容的提问来源于stack exchange,提问作者Krishnan Anantha Narayanan
相关产品推荐
相关产品推荐

