Search code examples
objective-cscenekit

SceneKit – Clone a node recursively


I am trying to clone all nodes (including their material) recursively. I want to change certain material properties in the cloned nodes without impacting the original node(materials).

This is what I have so far, but it does not seem to be working. Any change made on the new nodes is still reflected on the original nodes.

SCNNode *newRoot = [self.root clone];

[newRoot enumerateHierarchyUsingBlock:^(SCNNode * _Nonnull node, BOOL * _Nonnull stop) {
    SCNNode *oldNode = [self.root childNodeWithName:node.name recursively:YES];
    node.geometry = [oldNode.geometry copy];
    node.geometry.materials = [oldNode.geometry.materials copy];
}];

Solution

  • Try this code:

    #import "GameViewController.h"
    
    @implementation GameViewController
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        
        SCNView *sceneView = (SCNView *)self.view;
        SCNScene *scene = [SCNScene sceneNamed:@"art.scnassets/ship.scn"];
        sceneView.scene = scene;
        sceneView.allowsCameraControl = YES;
        sceneView.autoenablesDefaultLighting = YES;
        
        SCNMaterial *material = [SCNMaterial material];
        material.lightingModelName = SCNLightingModelPhysicallyBased;
        material.diffuse.contents = [NSColor redColor];
        
        SCNNode *ship = [scene.rootNode childNodeWithName:@"ship" 
                                              recursively:YES].childNodes[0];
        
        SCNNode *shipCopy = [ship clone];
        shipCopy.position = SCNVector3Make(10, 0, 0);
        
        SCNGeometry *geometryCopy = (SCNGeometry *)[ship.geometry copy];
        shipCopy.geometry = geometryCopy;
        [shipCopy.geometry replaceMaterialAtIndex:0 withMaterial:material];
        [scene.rootNode addChildNode:shipCopy];
    }
    @end
    

    enter image description here