Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to change orientation of a SCNNode to the Camera with ARKit

The code below places a SCNPlane onto the point touched, but the plane is oriented (rotated) to the position that the phone was in when the app started. I would ideally like to orient the Node to a physical wall or to the current orientation of the camera. How is this done with ARKit?

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    guard let touch = touches.first else {return}
    let result = sceneView.hitTest(touch.location(in: sceneView), types: [ARHitTestResult.ResultType.featurePoint])
    guard let hitResult = result.last else {return}
    let hitTransform = SCNMatrix4.init(hitResult.worldTransform)

    let hitVector = SCNVector3Make(hitTransform.m41, hitTransform.m42, hitTransform.m43)
    createPlane(position: hitVector)
}

func createPlane(position: SCNVector3) {

    let background = SCNNode()
    background.geometry = SCNPlane.init(width: 0.12, height: 0.10) // better set its size
    background.geometry?.firstMaterial?.diffuse.contents = "odinBW2.jpeg"
    background.position = position

    sceneView.scene.rootNode.addChildNode(background)

}
like image 352
Rob Schlackman Avatar asked Sep 24 '17 12:09

Rob Schlackman


Video Answer


2 Answers

If you want to align your node to the camera's orientation, just use SCNBillboardConstraint.

let yourNode = SCNNode()

let billboardConstraint = SCNBillboardConstraint()
billboardConstraint.freeAxes = [.X, .Y, .Z]
yourNode.constraints = [billboardConstraint]
like image 179
Jun Tanaka Avatar answered Sep 20 '22 13:09

Jun Tanaka


1 - This is how you get the rotation of the camera first:

Pitch - rotation around the X axis

let pitch = sceneView.session.currentFrame?.camera.eulerAngles.x 

Yawn - rotation around the Y axis

let yawn = sceneView.session.currentFrame?.camera.eulerAngles.y

Roll - rotation around the Z axis

let roll = sceneView.session.currentFrame?.camera.eulerAngles.z

2 - And then you can create the SCNVector3 that matches the rotations you want to keep (0 if you don't want any rotation on an axis) :

let newRotation = SCNVector3Make(pitch, yawn, roll)

3 - And then you attribute this eulerAngles to your node:

whateverNode.eulerAngles = newRotation
like image 28
Oscar Falmer Avatar answered Sep 21 '22 13:09

Oscar Falmer