0

I want to display a 3D model in SceneKit, but also want to place some 2D shapes to the model (e.g. a circle that can be tapped an triggers an interaction).

What is the best way to achieve this?

How it should look like:

enter image description here

Unsuccessful approach: used a regular SCNNode with small hight, but this does not behave as a 2D graphic (perspective changes)

enter image description here

Edit:

  • now I added the circle as a sprite kit node to the overlay view

    sceneView.overlaySKScene = SKScene.init(size: sceneView.frame.size)
    sceneView.overlaySKScene?.addChild(circle)
    
  • I also tried to get the screen-coordinates of the corresponding node, where I want to show the SpriteKit circle in front of:

    func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {
    
        let screenPoint = sceneView.projectPoint(interactionNode!.position)
    
        print(screenPoint)
    
        circle.position = CGPoint.init(x: CGFloat(screenPoint.x), y: CGFloat(screenPoint.y))
    

    }

However, sceneView.projectPoint gives me very weird results, even if the node is displayed in the middle of the screen, there are off-screen ranges returned...

Pascal
  • 2,590
  • 3
  • 21
  • 46
  • please show what you have done so far – Walucas Feb 08 '18 at 16:46
  • hey, so far I've simply added a regular SceneKit node (cylinder) with a very small hight (e.g. 0.001). However, this does not behave, as I want, because it looks more like a "sticker" on the model, which means its perspective changes, instead, it should always be shown the same way (like a HUD) – Pascal Feb 08 '18 at 17:26
  • Can you show some code? – Walucas Feb 08 '18 at 17:27
  • I have used the Xcode SceneKit interface builder, so there is no code, but I've uploaded pictures. It's actually a regular instance of `SCNNode` added to the model-node as child node. – Pascal Feb 08 '18 at 17:32
  • 1
    Use a Spritekit based overlay on the SCNView. See my answer here for an example: https://stackoverflow.com/questions/46298338/how-to-dynamically-create-annotations-for-3d-object-using-scenekit-arkit-in-io – Xartec Feb 08 '18 at 20:44
  • Hey, thanks for the hint to use projectPoint! It seems to be the right approach, however, this method gives me strange results: even if the node is placed in the middle of the screen, it gives me x-value of more than 600 and y less than -400 – Pascal Feb 09 '18 at 13:02
  • 1
    I see you already started a new question for that, just adding a link here for completion sake: https://stackoverflow.com/questions/48707732/mapping-3d-scenekit-node-position-to-2d-coordinate-projectpoint-doesnt-work Yes, use the worldposition property if the node is a child or is transformed. – Xartec Feb 09 '18 at 18:06

1 Answers1

2

You want to use overlaySKScene, which will allow you to place (performant) 2D Spritekit content "on top of" your Scenekit scene. Here's how I do it in my app:

First define Spritekit content that you want in your HUD:

class HUD: SKScene {
var shields: SKShapeNode(imageNamed: "shieldGrid")
var crosshairs = SKSpriteNode(imageNamed: "xenonHUD")
public var computerStatus = SKLabelNode()
public var enemyIndicator = SKLabelNode()

func shipHud.flashAlert( alert: String) {
   computerStatus.text = alert
}

Then, in your main view controller (where you instantiate your SceneView), make this class your scene's overview, and control it from there:

class MyGameViewController: UIViewController, SCNPhysicsContactDelegate, SCNSceneRendererDelegate {
var scnView: SCNView! 
// setup HUD
    shipHud = HUD(size: self.view.bounds.size)
    scnView.overlaySKScene = shipHud
    shipHud.flashAlert("Oh My God!")

}

Mixed SceneKit and Spritekit Content using overlaySKScene Mixed SceneKit and Spritekit Content using overlaySKScene

jglasse
  • 1,188
  • 12
  • 23
  • Thanks for the hint to use overlaySKScene! I now am able to show the 2d circle as a sprite kit node. However: I’m still having trouble to display it at the right position (which means, in front of the corresponding node in the 3d model)... do you have an idea how to always show the sprite kit node in front of the scene kit node? – Pascal Feb 09 '18 at 13:02
  • Sorry for the late response. Use projectPoint(_ point: SCNVector3) to convert your SceneKit node's 3D coordinates into 2D coordinates - just grab the first two elements of the SCNVector3 - they represent the X and Y coordinates in the scene renderer. – jglasse Feb 27 '18 at 16:35