Переместить 3D-объект с помощью якоря - PullRequest
0 голосов
/ 19 декабря 2018

Я сейчас работаю над приложением ARKit.Он должен иметь возможность размещать различные трехмерные объекты, перемещать их и сохранять карту мира.размещение и перемещение различных объектов не проблема, если я не использую якоря.Как только я ставлю якоря, чтобы сохранить карту мира, я не могу правильно перемещать объекты.Я использовал Apple Dev Project Взаимодействие с 3d-объектами как идею.Они удалили якорь, когда начали перемещать объект, и добавили новый.Но так как у меня есть разные объекты, это не работает должным образом.Когда пользователь нажимает кнопку добавления, он выбирает, какие объекты он хотел бы разместить.Это устанавливает название модели на правильную модель.Когда он нажимает на экран, он ставит якорь с именем модели.В рендерере (didAdd) будет создан правильный узел.Функция перемещения заменяет модель и привязку, но она не работает (вылетает при перезагрузке).Я думаю, что проблема в том, чтобы не допустить нулевых якорей, но я не нашел хорошего способа сделать это.

Можете ли вы мне помочь?

@objc func tapped(sender: UITapGestureRecognizer){
    let sceneView = sender.view as! ARSCNView
    let tapLocation = sender.location(in: sceneView)

    let hitTest = sceneView.hitTest(tapLocation, types: .existingPlaneUsingExtent)
    if !hitTest.isEmpty{
    print("Touched on the plane")


        let hitTestResult = hitTest.first!
        anchor = ARAnchor(name: "\(modelName)", transform: hitTestResult.worldTransform)
        print ("Anchor Name: , \(anchor!.name)" )

        self.sceneView.session.add(anchor: anchor!)

    }else{
        print("Not a plane")}
    }
@objc func moveNode(_ gesture: UIPanGestureRecognizer) {

    //1. Get The Current Touch Point
    let currentTouchPoint = gesture.location(in: sceneView)


    //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 = sceneView.hitTest(currentTouchPoint, options: nil).first else { return }

        //2b. Get The SCNNode Result
        let nodeHit = nodeHitTest.node

        //2c. Set As The Current Node
        selectedNode = nodeHit
        //if anchor is not nil remove from session



    }

    //3. 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 = sceneView.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
        selectedNode?.simdPosition = float3(newPosition.x, newPosition.y, newPosition.z)

    }

    //4. If The Gesture State Has Ended Remove The Reference To The Current Node
    if gesture.state == .ended{

        let selectedAnchor = sceneView.anchor(for: selectedNode!)
        if( selectedAnchor == nil){
            return

        }
        sceneView.session.remove(anchor: selectedAnchor!)
        guard let hitTest = sceneView.hitTest(currentTouchPoint, types: .existingPlane).first else { return }

        //3c. Convert To World Coordinates
        selectedNodeName = getParent(selectedNode)?.name

        let worldTransform = hitTest.worldTransform
        let newAnchor = ARAnchor(name: "\(selectedNodeName)", transform: worldTransform)
        print("NewAnchorName: , \(newAnchor.name)")
        sceneView.session.add(anchor: newAnchor)


        selectedNode = nil
        selectedNodeName = nil
        print("NewAnchorNameAfterNil: , \(newAnchor.name)")
        //adOrUpdateAnchor
    }
}
...