4
votes

I am trying to create a primitive with SceneKit and ARKit. For whatever reason, it is not working.

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)

Do I need to take in the camera coordinates as well?

2

2 Answers

5
votes

Your code looks good and it should work. I have tried it as the below code: after creating a new app with ARKit template, I have replaced the function 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)
}

It creates a box at the original point (0, 0, 0). Unfortunately your device is inside the box thus you cannot see that box straightly. To see the box, move your device far aways a bit.

The attached image is the box after moving my device:

enter image description here

If you want to see it immediately, move the box to front a bit, add colour and make the first material be double side (to see it even in or out side):

    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
votes

You should get the location tapped and use the world coordinates to place the cube properly. I'm not sure (0,0,0) is a normal location for ARKit. You can try something like this:
Put this in your viewDidLoad:

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

Then add this method:

@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)
}

Then when you tap on a plane surface detected, it will add a box on the plane where you tapped.