poojitha
poojitha

Reputation: 9

How to place an 3d object in fixed position of horizontal plane in iOS 11?

I have been trying to place an 3d object in horizontal plane but placed 3d object does not fixed into its position.

Currently i can able place 3d object in horizontal plane but placed 3d object in horizontal are moving. placed 3d object are not fixing into its position.

Here is the code i have trying to place 3d object into fixed position:

 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)

                }


            }

        }
    }

Here is the code to detect plane:

  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
                }
        }

Upvotes: 1

Views: 2065

Answers (2)

Artsem Sharubin
Artsem Sharubin

Reputation: 418

The problem is that your model is probably too big, if you pay attention to the default model from Apple, then it is the size -
enter image description here

And my uploaded model was 1000 times bigger - enter image description here

And this is why it not fixed, we need to make it less: enter image description here

And now our model have fixed position and behaves like a default model from apple:

enter image description here

Done:)

Upvotes: 0

PongBongoSaurus
PongBongoSaurus

Reputation: 7385

I think what you need to do is create an ARAnchor for your model:

Whenever you place a virtual object, always add an ARAnchor representing its position and orientation to the ARSession. After moving a virtual object, remove the anchor at the old position and create a new anchor at the new position. Adding an anchor tells ARKit that a position is important, improving world tracking quality in that area and helping virtual objects appear to stay in place relative to real-world surfaces.

As such this will probably point you in the right direction:

1st: Create a variable which will refer to your boxNode:

var boxNode: SCNNode?

2nd: Create an ARAnchor at the touch location e.g:

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)

}

3rd: In the rendererDidAddNode delegate callback intialize the model:

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!)

    }
}

Hope it helps...

Upvotes: 2

Related Questions