Как разместить трехмерный объект в фиксированном положении горизонтальной плоскости в iOS 11? - PullRequest
0 голосов
/ 15 мая 2018

Я пытался поместить 3d-объект в горизонтальной плоскости, но помещенный 3d-объект не зафиксирован на своей позиции.

В настоящее время я могу разместить 3d-объект в горизонтальной плоскости, но размещенный 3d-объект в горизонтальной плоскости движется,помещенный 3d-объект не фиксируется на своей позиции.

Вот код, который я пытаюсь поместить на 3D-объект в фиксированную позицию:

 override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

        if let touch = touches.first {

            // gives us the location of where we touched on the 2D screen.
            let touchLocation = touch.location(in: sceneView)

            // hitTest is performed to get the 3D coordinates corresponding to the 2D coordinates that we got from touching the screen.
            // That 3d coordinate will only be considered when it is on the existing plane that we detected.
            let results = sceneView.hitTest(touchLocation, types: .existingPlaneUsingExtent)

            // if we have got some results using the hitTest then do this.
            if let hitResult = results.first {


                let boxScene = SCNScene(named: "art.scnassets/porsche.scn")!
                //           var  boxScene = SCNScene(named: "art.scnassets/porsche.scn")!


                if let boxNode = boxScene.rootNode.childNode(withName: "car", recursively: true) {
                    print("box:::\(boxNode.childNodes)")


                    boxNode.position = SCNVector3(x: hitResult.worldTransform.columns.3.x, y: hitResult.worldTransform.columns.3.y, z: hitResult.worldTransform.columns.3.z)



                    // finally the box is added to the scene.
                    sceneView.scene.rootNode.addChildNode(boxNode)

                }


            }

        }
    }

Вот код для определения плоскости:

  func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {

                if anchor is ARPlaneAnchor {

         anchors can be of many types, as we are just dealing with horizontal plane detection we need to downcast anchor to ARPlaneAnchor
                    let planeAnchor = anchor as! ARPlaneAnchor

         creating a plane geometry with the help of dimentions we got using plane anchor.
                    let plane = SCNPlane(width: CGFloat(planeAnchor.extent.x), height: CGFloat(planeAnchor.extent.z))

                    // a node is basically a position.
                    let planeNode = SCNNode()

         setting the position of the plane geometry to the position we got using plane anchor.
                    planeNode.position = SCNVector3(x: planeAnchor.center.x, y: 0, z: planeAnchor.center.z)

                    // when a plane is created its created in xy plane instead of xz plane, so we need to rotate it along x axis.
                    planeNode.transform = SCNMatrix4MakeRotation(-Float.pi/2, 1, 0, 0)

                    //create a material object
                    let gridMaterial = SCNMaterial()

                    //setting the material as an image. A material can also be set to a color.
                    gridMaterial.diffuse.contents = UIImage(named: "art.scnassets/grid.png")

                    // assigning the material to the plane
                    plane.materials = [gridMaterial]


                    // assigning the position to the plane
                    planeNode.geometry = plane

                    //adding the plane node in our scene
                    node.addChildNode(planeNode)



                }

                else {

                    return
                }
        }

1 Ответ

0 голосов
/ 15 мая 2018

Я думаю, вам нужно создать ARAnchor для вашей модели:

Когда вы размещаете виртуальный объект, всегда добавляйте ARAnchor представляя свою позицию и ориентацию на ARSession. После перемещая виртуальный объект, снимите якорь в старом положении и создать новый якорь на новой позиции. Добавление якоря говорит ARKit что позиция важна, улучшая мировое качество отслеживания в этом площадь и помогающие виртуальные объекты остаются на месте относительно поверхности реального мира.

Таким образом, это, вероятно, укажет вам правильное направление:

1st: Создайте переменную, которая будет ссылаться на ваш boxNode:

var boxNode: SCNNode?

2-й: Создайте ARAnchor в месте прикосновения, например:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

    //1. Get The Current Touch Location & Perform An ARSCNHitTest
    guard let currentTouchLocation = touches.first?.location(in: sceneView),
        let hitTest = sceneView.hitTest(currentTouchLocation, types: .existingPlaneUsingExtent).first else { return }

    //2. Create An Anchor At The World Transform
    let anchor = ARAnchor(transform: hitTest.worldTransform)

    //3. Add It To The Scene
    sceneView.add(anchor: anchor)

}

3-й: В rendererDidAddNode delegate callback инициализировать модель:

func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {

    //1. If We Havent Created Our Box Node Then Create It
    if  boxNode == nil{

        //a. Check That Our SCNScene Is Valid
        guard let validScene =  SCNScene(named: "art.scnassets/porsche.scn"),
              let carRoot = validScene.rootNode.childNode(withName: "car", recursively: true) else { return }

        //b. Set The BoxNodes Position And Add It To The Anchor
        boxNode = carRoot
        boxNode?.position = SCNVector3(anchor.transform.columns.3.x, anchor.transform.columns.3.y, anchor.transform.columns.3.z)
        node.addChildNode(boxNode!)

    }
}

Надеюсь, это поможет ...

...