使用SceneKit和ARKit创建一个盒子

4
我正在尝试使用SceneKit和ARKit创建一个原始对象。但由于某些原因,它无法正常工作。
let box = SCNBox(width: 0.1, height: 0.1, length: 0.1, chamferRadius: 0)

    let node = SCNNode(geometry: box)

    node.position = SCNVector3(0,0,0)

    sceneView.scene.rootNode.addChildNode(node)

我需要同时获取相机坐标吗?
2个回答

6

你的代码看起来不错,应该可以正常工作。我已经尝试过它,下面是我的代码:创建一个新的带有ARKit模板的应用程序后,我替换了函数viewDidLoad。

override func viewDidLoad() {
    super.viewDidLoad()

    // Set the view's delegate
    sceneView.delegate = self

    let box = SCNBox(width: 0.1, height: 0.1, length: 0.1, chamferRadius: 0)
    let node = SCNNode(geometry: box)
    node.position = SCNVector3(0,0,0)
    sceneView.scene.rootNode.addChildNode(node)
}

它在原点(0,0,0)创建一个盒子。不幸的是,您的设备在盒子内部,因此您无法直接看到该盒子。要查看该盒子,请将您的设备远离一点。
附图是移动设备后的盒子: enter image description here
如果想立即看到它,可以将盒子前移一点,添加颜色并使第一个材质成为双面(以便在内外都能看到)。
    let box = SCNBox(width: 0.1, height: 0.1, length: 0.1, chamferRadius: 0)
    box.firstMaterial?.diffuse.contents = UIColor.red
    box.firstMaterial?.isDoubleSided = true
    let boxNode = SCNNode(geometry: box)
    boxNode.position = SCNVector3(0, 0, -1)
    sceneView.scene.rootNode.addChildNode(boxNode)

2

您应该获取被点击的位置,并使用世界坐标来正确放置立方体。我不确定(0,0,0)是否是ARKit中正常的位置。您可以尝试类似这样的代码:

将以下代码放入viewDidLoad中:

let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTapFrom))
tapGestureRecognizer.numberOfTapsRequired = 1
self.sceneView.addGestureRecognizer(tapGestureRecognizer)

然后添加此方法:
@objc func handleTapFrom(recognizer: UITapGestureRecognizer) {
    let tapPoint = recognizer.location(in: self.sceneView)
    let result = self.sceneView.hitTest(tapPoint, types: ARHitTestResult.ResultType.existingPlaneUsingExtent)

    if result.count == 0 {
        return
    }

    let hitResult = result.first

    let box = SCNBox(width: 0.1, height: 0.1, length: 0.1, chamferRadius: 0)

    let node = SCNNode(geometry: box)
    node.physicsBody = SCNPhysicsBody(type: SCNPhysicsBodyType.static, shape: nil)
    node.position = SCNVector3Make(hitResult.worldTransform.columns.3.x, hitResult.worldTransform.columns.3.y, hitResult.worldTransform.columns.3.z)

    sceneView.scene.rootNode.addChildNode(node)
}

当您轻触检测到的平面时,它将在您点击的平面上添加一个盒子。

我遇到了一个构建错误,然后更改了这部分代码。但是它仍然无法正常工作,所以我将其更改为以下内容:'node.position = SCNVector3Make((hitResult?.worldTransform.columns.3.x)!, (hitResult?.worldTransform.columns.3.y)!, (hitResult?.worldTransform.columns.3.z)!)' - paralaxbison
它没有添加一个立方体。我试图做一些简单的事情,只是在AR场景中添加一个立方体。我不确定为什么它不起作用。 - paralaxbison
0,0,0是ARKit中一个完全有效的位置。世界坐标系的原点是 - rickster
这里是您启动ARSession时设备的位置。如果自那时以来您没有移动,那么您的设备仍然在一个10厘米的立方体内,但由于内部面没有呈现,您看不到它。如果您稍微拉回一点,您应该会看到悬浮的立方体。虽然世界原点可能不是一个有用放置物品的地方,但本答案展示的基于命中测试的放置方式只是众多可能方法中的一种,可以将内容放置在有用的位置上。 - rickster

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接