【问题标题】:SCNKit: Hit test doesn't hit node's dynamically modified geometrySCENEKit:命中测试不会命中节点动态修改的几何图形
【发布时间】:2021-10-13 19:01:48
【问题描述】:

我遇到了一个问题,SCNView.hitTest 没有检测到我在 cpu 上动态修改的几何图形。

概述如下:我有一个节点使用从 MTLBuffer 的顶点创建的 SCNGeometry

func createGeometry(vertexBuffer: MTLBuffer, vertexCount: Int) -> SCNGeometry {
    let geometry = SCNGeometry(sources: [
        SCNGeometrySource.init(
            buffer: vertexBuffer,
            vertexFormat: .float3,
            semantic: .vertex,
            vertexCount: vertexCount,
            dataOffset: 0,
            dataStride: MemoryLayout<SIMD3<Float>>.stride),
    ], elements: [
        SCNGeometryElement(indices: ..., primitiveType: .triangles)
    ])
}


let vertexBuffer: MTLBuffer = // shared buffer
let vertexCount = ...

let node = SCNNode(geometry: createGeometry(vertexBuffer: vertexBuffer, vertexCount: vertexCount))

当应用程序运行时,我会在 SceneKit 更新循环中动态修改顶点缓冲区:

// In SceneKit update function

var ptr = vertexBuffer.contents().bindMemory(to: SIMD3<Float>.self, capacity: vertexCount)

for i in 0..<vertexCount {
    ptr[i] = // modify vertex
}

这个动态几何图形被 SceneKit 正确渲染。然而,当我尝试使用SCNView.hitTestnode 进行命中测试时,没有检测到针对修改后的几何体的命中。

我可以通过在修改数据后重新创建节点的几何来解决这个问题:

// after updating data
node.geometry = createGeometry(vertexBuffer: vertexBuffer, vertexCount: vertexCount)

但是这感觉就像是一个 hack。

对于动态变化的SCNGeometry 的节点,让命中测试可靠工作的正确方法是什么?

【问题讨论】:

  • 我不知道,如果我想说的方向正确,但这可能与 i.Ex 类似的问题。当您使用动画角色时,我前段时间读到,身体的变形仅由 GPU 执行,并且可以命中测试的数据实际上始终是原始数据(通常是人类性格),而不是修改过的性格。也许你的问题是相关的。
  • 这个线程中有一些有趣的建议可能会有所帮助:developer.apple.com/forums/thread/91618(创建新的 SCNGeometry 性能很好/使用 SCNMorpher)

标签: swift augmented-reality scenekit arkit metal


【解决方案1】:

我认为没有proper way 可以在您的情况下使命中测试可靠地工作。如果它不依赖于SceneKit/Metal 渲染循环和委托模式,这显然是可能的。但由于它完全依赖于它们,因此正如您之前所说,重新创建 SCNGeometry 的实例是一个不切实际的昂贵操作。所以,我完全同意@HamidYusifli。

【讨论】:

    【解决方案2】:

    当您执行命中测试搜索时,SceneKit 会沿着您指定的射线查找 SCNGeometry 对象。对于光线和几何体之间的每个交叉点,SceneKit 都会创建一个命中测试结果,以提供有关包含几何体的 SCNNode 对象以及几何体表面上交叉点位置的信息。

    您的问题是,当您在渲染时修改缓冲区的内容(MTLBuffer)时,SceneKit 不知道它,因此无法更新用于执行命中的 SCNGeometry 对象测试。

    所以我认为解决此问题的唯一方法是重新创建您的 SCNGeometry 对象。

    【讨论】:

    • 我或多或少地理解为什么它今天不起作用。问题是:重新创建 SCNGeometry 实例有点昂贵,那么有没有更好的方法让 SceneKit 知道几何体已更改,以便它可以更新用于命中测试的任何数据结构?
    • @MattBierner 不幸的是,没有比重新创建 SCNGeometry 对象更好的方法了。
    猜你喜欢
    • 2016-09-27
    • 2016-02-02
    • 2017-02-17
    • 2016-02-11
    • 2015-06-14
    • 2017-03-22
    • 1970-01-01
    • 1970-01-01
    • 2021-08-14
    相关资源
    最近更新 更多