Search code examples
iosswiftscenekithud

Recursion:: How to create a mini-view of 3d scenekit of self on top of self?


I have a 3d world with SceneKit, works great, can pan, zoom in/out but I want to create a mini-view of the 3d world on top of the larger 3d world. So if the user zooms in to a very fine resolution they still know where they are in space.

Most examples seem to overlay a different VC like SpriteKit on top of a SceneKit VC with something like overlaySKScene . The mini-version doesn't zoom in/out but will pan, change lighting etc but it will not accept gestures. This is more like recursion of how to put an mini-version of self on top of self.


Solution

  • Here is how I did it:

    You can simply add another camera to the scene, and render to a SCNLayer. Then, you can either use this layer within the scene as a material, or add it as a custom view on top of your scene.

    SCNScene *scene2 =[SCNScene scene];
    
    // We duplicate the scene by cloning the root node. 
    // I found that you cannot share the scene if you 
    // use the layer within it.
    [[scene2 rootNode] addChildNode:[root clone]];
    
    // Create a SCNLayer, set the scene and size
    SCNLayer *scnlayer = [SCNLayer layer];
    scnlayer.scene = scene2;
    scnlayer.frame = CGRectMake(0, 0, 600, 800);
    
    // "Layer" should be the name of your second camera
    scnlayer.pointOfView = [scene.rootNode childNodeWithName:@"Layer" recursively:YES];
    
    // Make sure it gets updated
    scnlayer.playing = YES;
    
    
    
    // Make a parent layer with a black background
    CALayer *backgroundLayer = [CALayer layer];
    backgroundLayer.backgroundColor = CGColorGetConstantColor(kCGColorBlack);
    backgroundLayer.frame = CGRectMake(0, 0, 600, 800);
    
    // Add the SCNLayer
    [backgroundLayer addSublayer:scnlayer];
    
    // Set the layer as the emissive material of an object
    SCNMaterial *material = plane.geometry.firstMaterial;
    material.emission.contents = scnlayer;
    

    I'm pretty sure this is not a great way to do it, but it worked for me.