代码之家  ›  专栏  ›  技术社区  ›  Ancuta Cozma

只能移动场景中放置的最后一个对象

  •  1
  • Ancuta Cozma  · 技术社区  · 6 年前

    嗨!我只能移动场景中放置的最后一个虚拟对象。当我添加另一个对象时,之前添加的对象保持静态,我无法对其执行任何操作。你能给我一个解决方案,让我在触摸时移动、缩放、旋转我想要的对象吗?

    1 回复  |  直到 6 年前
        1
  •  1
  •   BlackMirrorz    6 年前

    由于您没有发布任何代码,因此很难提供准确的答案。

    然而,为了跟踪当前 SCNNode 您希望使用,当您加载模型等时,可以将其存储为变量,例如:

    var currentNode: SCNNode!
    

    您也可以使用 name 属性,以保留对其更具体的引用。

    下面是一个这样做的示例:

    /// Example Of Loading An SCNScene & Setting It As The Current Node
    func loadModel(){
    
            let modelPath = "Character.scn"
    
            //1. Get The Reference To Our SCNScene & Get The Model Root Node
            guard let model = SCNScene(named: modelPath),
                let modelObject = model.rootNode.childNode(withName: "Root", recursively: false) else { return }
    
            //2. Scale It
            modelObject.scale = SCNVector3(0.4, 0.4, 0.4)
    
            //3. Add It To The Scene & Position It 1.5m Away From The Camera
            augmentedRealityView.scene.rootNode.addChildNode(modelObject)
            modelObject.position = SCNVector3(0, 0, -1.5)
    
            //4. Set It As The Current Node & Assign A Name
            currentNode = modelObject
            currentNode.name = "Character"
    
     }
    

    您还可以使用 SCNHitTest 其中:

    沿指定的光线查找SCNGeometry对象。对于每个 光线和几何体之间的交点,SceneKit创建 点击测试结果以提供有关SCNNode对象和 包含几何图形和交叉点的位置 几何曲面。

    这可以用来区分哪些节点被击中,例如:

    /// Detects A Tap On An SCNNode
    ///
    /// - Parameter gesture: UITapGestureRecognizer
    @objc func detectTap(_ gesture: UITapGestureRecognizer){
    
        //1. Get The Current Touch Point
        let currentTouchPoint = gesture.location(in: self.augmentedRealityView)
    
        //2a. Perform An SCNHitTest To Detect If An SCNNode Has Been Touched
        guard let nodeHitTest = self.augmentedRealityView.hitTest(currentTouchPoint, options: nil).first else { return }
    
        if nodeHitTest.node == currentNode{
            print("The Current Node Has Been Touched")
        }
    
        //Or To See Which Node Has Been Touched
        if nodeHitTest.node.name == "The Model"{
            print("The Model Has Been Touched")
        }
    }
    

    处理此问题的另一种方法是向视图中添加UITapgestureRecognitor,并根据结果启用交互,例如以这种方式设置currentNode,例如:

    /// Detects A Tap On An SCNNode & Sets It As The Current Node
    ///
    /// - Parameter gesture: UITapGestureRecognizer
    @objc func detectTap(_ gesture: UITapGestureRecognizer){
    
        //1. Get The Current Touch Point
        let currentTouchPoint = gesture.location(in: self.augmentedRealityView)
    
        //2a. Perform An SCNHitTest To Detect If An SCNNode Has Been Touched
        guard let nodeHitTest = self.augmentedRealityView.hitTest(currentTouchPoint, options: nil).first else { return }
    
        //2b. Set It As The Current Node
        currentNode = nodeHitTest.node
    }
    

    然后,您可以应用逻辑来确保 currentNode 移动等:

    /// Moves An SCNNode
    ///
    /// - Parameter gesture: UIPanGestureRecognizer
    @objc func moveNode(_ gesture: UIPanGestureRecognizer) {
    
        //1. Get The Current Touch Point
        let currentTouchPoint = gesture.location(in: self.augmentedRealityView)
    
        //2. If The Gesture State Has Begun Perform A Hit Test To Get The SCNNode At The Touch Location
        if gesture.state == .began{
    
            //2a. Perform An SCNHitTest To Detect If An SCNNode Has Been Touched
            guard let nodeHitTest = self.augmentedRealityView.hitTest(currentTouchPoint, options: nil).first else { return }
    
            //2b. Get The SCNNode Result
            if nodeHitTest.node == currentNode{
    
                //3a. If The Gesture State Has Changed Then Perform An ARSCNHitTest To Detect Any Existing Planes
                if gesture.state == .changed{
    
                    //3b. Get The Next Feature Point Etc
                    guard let hitTest = self.augmentedRealityView.hitTest(currentTouchPoint, types: .existingPlane).first else { return }
    
                    //3c. Convert To World Coordinates
                    let worldTransform = hitTest.worldTransform
    
                    //3d. Set The New Position
                    let newPosition = SCNVector3(worldTransform.columns.3.x, worldTransform.columns.3.y, worldTransform.columns.3.z)
    
                    //3e. Apply To The Node
                    currentNode.simdPosition = float3(newPosition.x, newPosition.y, newPosition.z)
    
                }
    
            }
        }
    }
    

    这应该足以为您指明正确的方向。。。