2

I've just ran a couple of tests comparing the performance of different ways of loading/creating a scene to see the performance impact. The test was simply rendering a 32x32 grid of cubes and eyeballing the CPU usage, memory, energy and rendering times. Not very scientific but there were some clear results. The four tests consisted of...

  1. Load a .dae, e.g. SCNScene(named: "grid.dae")
  2. Converting a .dae to .scn file in XCode and loadinf that
  3. Building a grid in the Scnenekit editor manually using a reference node
  4. Building a grid programatically using an SCNReference node (see code at bottom of question)

I expected 1 & 2 to be broadly the same and they were.

I expected test 3 to have much better performance than tests 1 & 2, and it did. The CPU load and energy usage was very low. It had half the memory foootprint and the rendering time was a fraction of the rendering times for test 1&2.

I was hoping test 4 would match test 3, but it didn't. It appeared to be the same or worse than tests 1&2.

    // Code for test 4  

    let boxPath = Bundle.main.path(forResource: "box", ofType: "scn")
    let boxUrl = URL(fileURLWithPath: boxPath!)
    let offset: Int = 16

    for xIndex:Int in 0...32 {
      for yIndex:Int in 0...32 {
           let boxReference = SCNReferenceNode(url: boxUrl)
           scene.rootNode.addChildNode(boxReference!)
           boxReference?.position.x = Float(xIndex - offset)
           boxReference?.position.y = Float(yIndex - offset)
           boxReference?.load()
        }
     }

Is the performance advantage that SceneKit's level editor provides available to developers and I'm just going about it wrong, or is Scenekit/XCode doing something bespoke under the hood?

UPDATE

In response to Confused's comment, I tried using the flattenedCone method on SCNNode. Here is a variation on the original code using that technique...

        let boxPath = Bundle.main.path(forResource: "box", ofType: "scn")
        let boxUrl = URL(fileURLWithPath: boxPath!)
        let offset: Int = 16
        let testNode = SCNNode()

        for xIndex:Int in 0...32 {
            for yIndex:Int in 0...32 {
                let boxReference = SCNReferenceNode(url: boxUrl)
                testNode.addChildNode(boxReference!)
                boxReference?.position.x = Float(xIndex - offset)
                boxReference?.position.y = Float(yIndex - offset)
                boxReference?.load()
            }
        }

        let optimizedNode = testNode.flattenedClone()
        scene.rootNode.addChildNode(optimizedNode)
gargantuan
  • 8,888
  • 16
  • 67
  • 108
  • There's some command that reduces/flattens 3D nodes somehow, but I have forgotten how to even search for it. If you find that, I think you can add that to your programmatically created scenes and get similar performance to the Scene Editor, which is probably doing this. – Confused Oct 02 '16 at 16:22
  • 1
    Found it: flattenedClone() it used to be called: http://stackoverflow.com/questions/27715237/scene-kit-performance-with-cube-test and here's the docs: https://developer.apple.com/reference/scenekit/scnnode/1407960-flattenedclone hope that helps a little. – Confused Oct 02 '16 at 16:28
  • Went on a hunt after reading your comment and found it myself too. Just updated the test by creating the grid in a `testNode`, calling `testNode.flattenedCone()` and assigning the result to `optimizedNode` and adding `optimizedNode` to the scene. The result seems significantly worse. A longer loading time, a big spike in memory usage, presumably while the optimisation takes place and then the metrics return to the same numbers I am seeing in test 1 and 2. – gargantuan Oct 02 '16 at 16:35
  • DOH! There must be a way to get amazing performance with SceneKit and dozens of objects all the same. I do remember it somewhere else... and there being some "trick" to getting this to work correctly. I also remember nothing in SceneKit working as advertised first time out. ie that EVERYTHING required knowing the "tricks" of doing it "right". – Confused Oct 02 '16 at 16:38
  • 1
    Yeah, I've been working mostly with Swift 3 in the XCode 8 beta's prior to the XCode 8 release. Add to that SceneKit's level editor flakiness, it's not been a fun experience. Anyway, I've updated my examples to include the flattenedCone attempt. It's still useful to be made aware of flattenedCone. – gargantuan Oct 02 '16 at 16:40
  • 1
    I have a lot of trouble reading this, but it seems like there's some merging going on that helps: http://stackoverflow.com/questions/14718407/scenekit-on-os-x-with-thousands-of-objects/22207363#22207363 – Confused Oct 02 '16 at 17:03

0 Answers0