SCNLevelOfDetails 委托/通知 [英] SCNLevelOfDetails delegate/notification

查看:19
本文介绍了SCNLevelOfDetails 委托/通知的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 SceneKit 中使用 SCNLevelOfDetails.

I'm using SCNLevelOfDetails with SceneKit.

我想知道是否有办法知道引擎何时更改特定节点几何的 levelOfDetails.

I was wondering if there's a way to know when the engine changes the levelOfDetails for a particular node's geometry.

非常感谢.

推荐答案

我正在回答我自己的问题.为了提供更多上下文,我们需要知道 LOD 何时更改以停止空闲动画,我们的模型已蒙皮.如果您在 LOD 更改时不禁用此动画会发生什么情况,即地理遍布整个地方并且看起来是错误的.

I'm answering my own question. To give more context, we needed to know when the LOD would change in order to stop an idle animation, our model is skinned. What happens if you don't disable this animation when the LOD changes is that the geo goes all over the place and it looks wrong.

我们的解决方案是克隆渲染的节点geo,使用这个geo克隆创建一个节点,并为它提供不同的LOD,当它很远时,将此节点添加到层次结构中.这样节点就不受关节和动画的影响.我们称这个节点为lowLODNode.

The solution for us was to clone the rendered node geo, create a node using this geo clone and give it our different LOD for when it's far, add this node to the hierarchy. This way the node is not affected by the joints and the animation. We call this node lowLODNode.

当您渲染的节点太远时,它的 LOD 将为 nil,因此它会消失,而 lowLODNode 会启动.请注意,lowLODNode 在靠近时的 LOD 为 nil.

Your rendered node will have LOD of nil when it's too far so it disappear and the lowLODNode kicks in. Note the the lowLODNode has a LOD of nil when it's close.

为了禁用动画,我们使用渲染器循环来计算与 POV 的距离,并在达到 LOD 阈值时禁用它.请注意,我们每 0.25 秒迭代 1000 多个节点,由于 simd 库,此计算平均只需要 0.0016 秒.

To disable the animation we use the renderer loop to compute distance from POV and disable it if the LOD threshold is reached. Note that we are iterating through more than a 1000 nodes every 0.25 seconds, this calculation only takes 0.0016 second in average thanks to the simd library.

我正在添加一个代码示例来展示该技术:

I'm adding a code example to show off the technique:

private func setupLOD() {
    // Keep animation and LOD working with a rigged node.
    // Scene graph
    // YourNodeSubclass
    //  - loadedDAENode
    //      - rigNode
    //      - geoGroupNode
    //          - geoNode -> this one has a SCNGeometry, empty geo when far LOD = [ geoNode.geo, nil ]
    //      - lowLODNode -> this one has the low poly versions and an empty geo when close LOD = [ nil, lowPoly1, lowPoly2, ... ]

    // LOD for the geometry affected by the rig. The geo disappear when far enough. Animations are working.
    let lowLevelMain = SCNLevelOfDetail(geometry: nil, worldSpaceDistance: 3.0)
    renderedNode.childNode(withName: "\(renderedNodeName)_geo", recursively: true)?.geometry?.levelsOfDetail = [lowLevelMain]

    // 1) Load low poly geo and eventual LOD geos from folder(s).
    // 2) Copy each LOD geo.
    // 3) Create a geo, make it transparent. This will be the high LOD geo the default one.
    // 4) Create a lowLODNode using this geo.
    // 5) Ceate your [LOD]
    // 6) Assign LOD to lowLODNode geometry
    // 7) Add the lowLODNode as a child to the rendered node

    // 1) 2)
    if let lowVersionScene = SCNScene(named: "art.scnassets/yourScene.dae"), let itemNode = lowVersionScene.rootNode.childNode(withName: "rootNodeName", recursively: false), let geo = itemNode.childNode(withName: "nodeWithGeo", recursively: true)?.geometry?.copy() as? SCNGeometry {
        // 3)
        let tranparentCube = SCNBox(width: 0.1, height: 0.1, length: 0.1, chamferRadius: 0.0)
        tranparentCube.firstMaterial?.diffuse.contents = UIColor.clear
        // 4)
        let lowLODNode = SCNNode(geometry: tranparentCube)
        // 5)
        let lowLOD = SCNLevelOfDetail(geometry: geo, worldSpaceDistance: 3.0)
        // 6)
        lowLODNode?.levelsOfDetail = [lowLOD]
        // 7)
        renderedNode.addChildNode(lowLODNode)
    }
}

唯一的缺点是我们必须使用基于距离而不是像素大小的 LOD,因为我们需要知道何时禁用动画并且不想以像素为单位计算对象的大小.

The only downside to this is that we have to use LOD based on distance NOT pixel size because we need to know when to disable the animation and don't want to compute the size of the object in pixels.

使用这种技术,我们能够真正降低 CPU 和 GPU 的使用率.

We were able to really lower the CPU and GPU usage using this technique.

这篇关于SCNLevelOfDetails 委托/通知的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆