【问题标题】:remove nodes from scene after use ARSCNView使用 ARSCNView 后从场景中删除节点
【发布时间】:2018-11-10 23:56:42
【问题描述】:

我正在制作一个使用 ARKit 来测量两点之间的应用程序。目标是能够测量长度,存储该值,然后测量宽度并存储。

我遇到的问题是在获得测量值后处理节点。

到目前为止的步骤: 1)添加了一个带有restartFunction的按钮。这可以重置测量值,但没有从场景中移除球体,并且也使下一次测量变得笨拙。

2) 对 > 2 个节点设置限制。这个功能效果最好。但是球体仍然漂浮在场景中。

这是我获得的最佳结果的屏幕截图。

@objc func handleTap(sender: UITapGestureRecognizer) {
    let tapLocation = sender.location(in: sceneView)
    let hitTestResults = sceneView.hitTest(tapLocation, types: .featurePoint)
    if let result = hitTestResults.first {
        let position = SCNVector3.positionFrom(matrix: result.worldTransform)

        let sphere = SphereNode(position: position)


        sceneView.scene.rootNode.addChildNode(sphere)

        let tail = nodes.last

        nodes.append(sphere)

        if tail != nil {
            let distance = tail!.position.distance(to: sphere.position)
            infoLabel.text = String(format: "Size: %.2f inches", distance)

            if nodes.count > 2 {

                nodes.removeAll()

            }
        } else {
            nodes.append(sphere)

        }
    }
}

我是 Swift 新手(一般是编码),我的大部分代码都来自拼凑教程。

【问题讨论】:

  • 我不是一个 SceneKit 编码器,但听起来 nodes.removeAll() 没有受到打击。你用断点测试过吗?

标签: swift arkit


【解决方案1】:

我认为这里的问题是您实际上并没有删除您添加到层次结构中的SCNNodes

虽然您通过调用 nodes.removeAll() 从我假设的 SCNNodes 数组中删除节点,但您首先需要从场景层次结构中实际删除它们。

因此,您需要在要删除的任何节点上调用以下函数:

removeFromParentNode()

很简单:

从其父节点的子节点数组中删除该节点。

因此,您会做这样的事情,首先从层次结构中删除节点,然后从数组中删除它们:

for nodeAdded in nodesArray{
    nodeAdded.removeFromParentNode()
}

nodesArray.removeAll()

因此,根据提供的代码,您可以执行以下操作:

if nodes.count > 2 {

    for nodeAdded in nodes{
        nodeAdded.removeFromParentNode()
    }

    nodes.removeAll()

}

为了将来参考,如果你想从你的层次结构中删除所有SCNNodes,你也可以调用:

self.augmentedRealityView.scene.rootNode.enumerateChildNodes { (existingNode, _) in
    existingNode.removeFromParentNode()
}

其中 self.augmentedRealityView 指的是变量:

var augmentedRealityView: ARSCNView!

这是一个非常基本的工作示例,基于您提供的代码(并从中修改):

/// Places A Marker Node At The Desired Tap Point
///
/// - Parameter sender: UITapGestureRecognizer
@objc func handleTap(_ sender: UITapGestureRecognizer) {

    //1. Get The Current Tap Location
    let currentTapLocation = sender.location(in: sceneView)

    //2. Check We Have Hit A Feature Point
    guard let hitTestResult = self.augmentedRealityView.hitTest(currentTapLocation, types: .featurePoint).first else { return }

    //3. Get The World Position From The HitTest Result
    let worldPosition = positionFromMatrix(hitTestResult.worldTransform)

    //4. Create A Marker Node
    createSphereNodeAt(worldPosition)

    //5. If We Have Two Nodes Then Measure The Distance
    if let distance = distanceBetweenNodes(){
        print("Distance == \(distance)")
    }

}

/// Creates A Marker Node
///
/// - Parameter position: SCNVector3
func createSphereNodeAt(_ position: SCNVector3){

    //1. If We Have More Than 2 Nodes Remove Them All From The Array & Hierachy
    if nodes.count >= 2{

        nodes.forEach { (nodeToRemove) in
            nodeToRemove.removeFromParentNode()
        }

        nodes.removeAll()
    }

    //2. Create A Marker Node With An SCNSphereGeometry & Add It To The Scene
    let markerNode = SCNNode()
    let markerGeometry = SCNSphere(radius: 0.01)
    markerGeometry.firstMaterial?.diffuse.contents = UIColor.cyan
    markerNode.geometry = markerGeometry
    markerNode.position = position
    sceneView.scene.rootNode.addChildNode(markerNode)

    //3. Add It To The Nodes Array
    nodes.append(markerNode)
}

/// Converts A matrix_float4x4 To An SCNVector3
///
/// - Parameter matrix: matrix_float4x4
/// - Returns: SCNVector3
func positionFromMatrix(_ matrix: matrix_float4x4) -> SCNVector3{

    return SCNVector3(matrix.columns.3.x, matrix.columns.3.y, matrix.columns.3.z)

}

/// Calculates The Distance Between 2 Nodes
///
/// - Returns: Float?
func distanceBetweenNodes()  -> Float? {

    guard let firstNode = nodes.first, let endNode = nodes.last else { return nil }
    let startPoint = GLKVector3Make(firstNode.position.x, firstNode.position.y, firstNode.position.z)
    let endPoint = GLKVector3Make(endNode.position.x, endNode.position.y, endNode.position.z)
    let distance = GLKVector3Distance(startPoint, endPoint)
    return distance
}

有关可能有助于您的开发的测量应用程序示例,您可以查看此处:ARKit Measuring Example

希望对你有帮助...

【讨论】:

  • 非常感谢。这帮助我解决了删除节点的问题,并且也了解了我正在做什么以找到更好的编写方法。
  • 没问题 :) 很高兴它有帮助 :)
【解决方案2】:

这看起来像是一个逻辑问题。在检查 tail 是否不为零之前,您正在将 nodes.last 分配给 tail。所以它永远不会是 != nil 所以你永远不会在 else 中执行 nodes.append(sphere)。

我同意@dfd。设置断点以确保在继续之前正在执行代码。

【讨论】:

    猜你喜欢
    • 2015-04-28
    • 2023-03-12
    • 2014-09-02
    • 2016-04-22
    • 1970-01-01
    • 1970-01-01
    • 2021-12-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多