我希望能够使用SceneKit
向球体表面添加形状。我从一个简单的例子开始,我只是试图为球体表面的一部分着色另一种颜色。我希望这是一个可以点击,选择等的对象......所以我的想法是使用自定义SCNNodes
对象为几何体添加SCNShape
形状。
我现在拥有的是一个蓝色正方形,我从一系列点中绘制并添加到包含红色球体的场景中。它基本上与球体上的一个点相切,但真正的目标是在表面上绘制它。 SceneKit中有什么东西可以让我这样做吗?我是否需要进行一些数学/几何以使其与球体形状相同或映射到球体的坐标?我正在尝试在SceneKit的范围之外做什么?
如果这个问题过于宽泛,我会很高兴有人能指出我的书籍或资源来了解我所缺少的东西。我对SceneKit和3D一般都很陌生,只是玩得很开心。
以下是我现在拥有的游乐场代码:
import UIKit
import SceneKit
import XCPlayground
class SceneViewController: UIViewController {
let sceneView = SCNView()
private lazy var sphere: SCNSphere = {
let sphere = SCNSphere(radius: 100.0)
sphere.materials = [self.surfaceMaterial]
return sphere
}()
private lazy var testScene: SCNScene = {
let scene = SCNScene()
let sphereNode: SCNNode = SCNNode(geometry: self.sphere)
sphereNode.addChildNode(self.blueChildNode)
scene.rootNode.addChildNode(sphereNode)
//scene.rootNode.addChildNode(self.blueChildNode)
return scene
}()
private lazy var surfaceMaterial: SCNMaterial = {
let material = SCNMaterial()
material.diffuse.contents = UIColor.redColor()
material.specular.contents = UIColor(white: 0.6, alpha: 1.0)
material.shininess = 0.3
return material
}()
private lazy var blueChildNode: SCNNode = {
let node: SCNNode = SCNNode(geometry: self.blueGeometry)
node.position = SCNVector3(0, 0, 100)
return node
}()
private lazy var blueGeometry: SCNShape = {
let points: [CGPoint] = [
CGPointMake(0, 0),
CGPointMake(50, 0),
CGPointMake(50, 50),
CGPointMake(0, 50),
CGPointMake(0, 0)]
var pathRef: CGMutablePathRef = CGPathCreateMutable()
CGPathAddLines(pathRef, nil, points, points.count)
let bezierPath: UIBezierPath = UIBezierPath(CGPath: pathRef)
let shape = SCNShape(path: bezierPath, extrusionDepth: 1)
shape.materials = [self.blueNodeMaterial]
return shape
}()
private lazy var blueNodeMaterial: SCNMaterial = {
let material = SCNMaterial()
material.diffuse.contents = UIColor.blueColor()
return material
}()
override func viewDidLoad() {
super.viewDidLoad()
sceneView.frame = self.view.bounds
sceneView.backgroundColor = UIColor.blackColor()
self.view.addSubview(sceneView)
sceneView.autoenablesDefaultLighting = true
sceneView.allowsCameraControl = true
sceneView.scene = testScene
}
}
XCPShowView("SceneKit", view: SceneViewController().view)
答案 0 :(得分:6)
如果要将2D内容映射到3D SceneKit对象的表面,并使2D内容成为动态/交互式,最简单的解决方案之一是将SpriteKit用于2D内容。您可以将球体的漫反射内容设置为SKScene
,并在该场景中创建/定位/修饰SpriteKit节点,以将它们排列在球体的面上。
如果您希望此内容响应点击事件...在SceneKit视图中使用hitTest
会获得SCNHitTestResult
,然后您可以获取该点的纹理坐标球。从纹理坐标,您可以转换为SKScene
坐标并生成节点,运行操作或其他任何内容。
有关详细信息,您最好的选择可能是Apple的SceneKitReel示例代码项目。这是在WWDC14上为iOS引入SceneKit的演示。在那个演示中有一个“幻灯片”,其中油漆球在旋转的圆环上从相机飞出并留下油漆溅到它们的位置 - 圆环有一个SpriteKit场景作为其材料,并且在碰撞时留下飞溅的技巧基本相同命中测试 - >纹理坐标 - >上面概述的SpriteKit坐标方法。
答案 1 :(得分:3)
David Ronnqvist的SceneKit书中有一个值得关注的例子(EarthView示例,一个说话的地球,第5章)。该示例构建了一个3D图钉,然后将其附加到水龙头位置的地球表面。
你的问题更复杂,因为你正在构建一个覆盖球体一部分的形状。你的" square"实际上是一个球形梯形,是由四个大圆弧限定的球体的一部分。我可以看到三种可能的方法,具体取决于您最终寻找的内容。
最简单的方法是使用图像作为球体表面的材质。这种方法在Ronnqvist EarthView示例中得到了很好的说明,该示例使用多个图像来显示地球表面。你不是画大陆,而是画你的广场。不过,这种方法并不适合交互性。看看SCNMaterial
。
另一种方法是使用命中测试结果。这已记录在SCNSceneRenderer
(SCNView
符合)和SCNHitTest
上。使用命中测试结果,您可以拉出被轻击的面,然后拉出其几何元素。但是,这不会让你一直回家,因为SceneKit使用三角形SCNSphere
,你正在寻找四边形。您还将被限制为与SceneKit的基础线框表示对齐的正方形。
如果你想完全控制" square"绘制,包括改变其相对于赤道的角度,我认为你必须从头开始构建自己的几何。这意味着计算每个角点的纬度/经度,然后在这些点之间生成弧,然后计算沿弧的一堆中间点。您必须添加一个软糖因子,将中间点提升到略高于球体表面的位置,并建立自己的四边形或三角形条带。这里的课程是SCNGeometry
,SCNGeometryElement
和SCNGeometrySource
。