0

I am working with SceneKit and ARKit. I have made a collectionView with an array of emoji's. Now I want the user to be able to select the emoji from collectionView and when he/she touches the screen that selected emoji will be placed in 3D.

How can I do that? I think I have to create a function for the Node, but still my idea is blurry in the mind and I am not very much clear.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
khan
  • 49
  • 5

1 Answers1

0

As far as any emoji is a 2D element, it's better to use a SpriteKit framework to upload them, not a SceneKit. But, of course, you might choose a SceneKit as well. So, there are two ways you can work with emojis in ARKit:

  • Using SpriteKit. In that case all the 2D sprites you spawn in ARSKView are always face the camera. So, if the camera moves around a definite point of real scene, all the sprites are rotates about their pivot point facing a camera.

  • Using SceneKit. In ARSCNView you can use all your sprites as a texture for 3D geometry. This texture could be for a plane, cube, sphere, or any custom model, it's up to you. To make, for example, a plane (with emojis texture on it) to face a camera use SCNBillboardConstraint constraint.

Here's how you code in ViewController might look like:

// Element's index coming from `collectionView`
var i: Int = 0

func view(_ view: ARSKView, nodeFor anchor: ARAnchor) -> SKNode? {
    let emojiArray = ["","","","",""]
    let emojiNode = SKLabelNode(text: emojiArray[i])           
    emojiNode.horizontalAlignmentMode = .center
    emojiNode.verticalAlignmentMode = .center
    return emojiNode
}

...and in Scene.swift file:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    guard let sceneView = self.view as? ARSKView else { return }

    if let currentFrame = sceneView.session.currentFrame {
        var translation = matrix_identity_float4x4
        translation.columns.3.z = -0.75               // 75 cm from camera
        let transform = simd_mul(currentFrame.camera.transform, translation)
        let anchor = ARAnchor(transform: transform)
        sceneView.session.add(anchor: anchor)
    }
}

Or, if you use hit-testing, your code might look like this:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    guard let sceneView = self.view as? ARSKView else { return }

    if let touchLocation = touches.first?.location(in: sceneView) {
        if let hit = sceneView.hitTest(touchLocation, types: .featurePoint).first {
            sceneView.session.add(anchor: ARAnchor(transform: hit.worldTransform))
        }
    }
}

If you'd like to create an UICollectionView overlay containing emojis to choose from, read the following post.

If you'd like to create an SKView overlay, containing emojis to choose from, read the following post.

Zoe
  • 27,060
  • 21
  • 118
  • 148
Andy Jazz
  • 49,178
  • 17
  • 136
  • 220
  • ok so does it mean SCNnode doesn't support the 2D format. I understand this method but how to pass it to collection view i want the node to be selected from collection view – khan Jun 09 '19 at 08:29