Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is SCNNode.presentation.position so relatively slow, and is there a workaround?

I traced a major performance bottleneck in my SceneKit app to a nested loop being run a few thousand times. In that loop is a bunch of code that zooms along quite happily, apart from this one line:

var scenePos = presentation.position

It's over 100 times slower than just asking for the position PLUS dozens of other calculations, comparisons, array lookups & method calls combined that I was doing inside the same loop. I'm surprised no-one seems to have commented on this yet that I can find.

Why is this, and is there a workaround for it apart from making a copy of each node's presentation.position yourself each frame so you don't have to keep asking the presentation node for it? Thanks.

Edits: presentation.position is only ever being read, never written to. No boundingBox is ever edited. I'm using a dynamic SCNPhysicsBody for a few of the SCNNodes, but the vast majority are static.

like image 320
DenverCoder9 Avatar asked Nov 07 '22 21:11

DenverCoder9


1 Answers

Here's the workaround I'm currently using (for this, and also the separate issue that presentation.position can be zero if physics has never been run for that node). It's orders of magnitude faster, as nearly all my nodes are not dynamic.

// When you're not sure if physics has first run yet
func currentScenePos() -> SCNVector3 {
    if physicsBody?.type == .dynamic {
        var scenePos = presentation.position
        if scenePos.isZero() {
            // Looks like the physics hasn't run on this node yet. Use the regular position.
            // If that's zero too, it must really be at the scene origin.
            scenePos = position
        }
        return scenePos
    } else {
        // Non-dynamic physics. Just use position, it's a lot faster.
        return position
    }
}
like image 180
DenverCoder9 Avatar answered Nov 15 '22 06:11

DenverCoder9