web-dev-qa-db-fra.com

Comment garder ARKit SCNNode en place

Hé, j'essaie de comprendre. Comment garder un nœud simple en place. Alors que je me promène dans ARKit

Code:

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

    if let planeAnchor = anchor as? ARPlaneAnchor {

    if planeDetected == false { // Bool only allows 1 plane to be added
            planeDetected = true
        self.addPlane(node: node, anchor: planeAnchor)
    }

    }
}

Cela ajoute le SCNNode

    func addPlane(node: SCNNode, anchor: ARPlaneAnchor) {

    // We add the anchor plane here

    let showDebugVisuals = Bool()
    let plane = Plane(anchor, showDebugVisuals)
    planes[anchor] = plane
    node.addChildNode(plane)



    // We add our custom SCNNode here 

    let scene = SCNScene(named: "art.scnassets/PlayerModel.scn")!
    let Body = scene.rootNode.childNode(withName: "Body", recursively: true)!

    Body.position = SCNVector3.positionFromTransform(anchor.transform)
    Body.movabilityHint = .movable
    wrapperNode.position = SCNVector3.positionFromTransform(anchor.transform)

    wrapperNode.addChildNode(Body)

    scnView.scene.rootNode.addChildNode(wrapperNode)

J'ai essayé d'ajouter un Plane/Anchor Node et d'y mettre le nœud "Body" mais il bouge toujours. J'ai pensé que cela avait peut-être quelque chose à voir avec la fonction de mise à jour.

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

O probablement le réglage de position

wrapperNode.position = SCNVector3.positionFromTransform(anchor.transform)

Iv'e a parcouru chaque source/fichier de projet/vidéo sur Internet et personne n'a de solution simple à ce problème simple.

20
Hunter

Il existe deux types de "déplacements" qui pourraient se produire ici.


La première est qu'ARKit affine continuellement son estimation de la façon dont la position de l'appareil dans le monde réel correspond à l'espace de coordonnées abstrait dans lequel vous placez le contenu virtuel. Par exemple, supposons que vous placez un objet virtuel à (0, 0, -0.5), Et déplacez ensuite votre appareil vers la gauche de 10 cm exactement. L'objet virtuel ne semble ancré dans l'espace physique que si ARKit suit précisément le mouvement. Mais l'odométrie visuellement inertielle n'est pas une science exacte, il est donc possible qu'ARKit pense que vous vous êtes déplacé vers la gauche de 10,5 cm - dans ce cas, votre objet virtuel semblera "glisser" vers la droite de 5 mm, même si son la position dans l'espace de coordonnées ARKit/SceneKit reste constante.

Vous ne pouvez pas vraiment faire grand-chose à ce sujet, sauf espérer Apple fabrique des appareils avec de meilleurs capteurs, de meilleures caméras ou de meilleurs processeurs/GPU et améliore la science du suivi du monde. (Dans la plénitude de temps, c'est probablement une valeur sûre, bien que cela n'aide probablement pas avec votre projet actuel.)


Puisque vous avez également affaire à la détection d'avion, il y a une autre ride. ARKit affine continuellement ses estimations de l'endroit où se trouve un avion détecté. Ainsi, même si la position réelle de l'avion ne change pas, sa position dans l'espace de coordonnées ARKit/SceneKit l'est.

Ce type de mouvement est généralement une bonne chose - si vous voulez que votre objet virtuel apparaisse ancré à la surface du monde réel, vous voulez être sûr de l'endroit où se trouve cette surface. Vous verrez un certain mouvement lorsque la détection de l'avion sera plus sûre de la position de la surface, mais après un court instant, vous devriez voir moins de "glissement" lorsque vous déplacez la caméra pour les objets virtuels ancrés dans le plan que ceux qui flottent simplement dans le monde espace.


Dans votre code, cependant, vous ne profitez pas de la détection des avions pour que votre contenu personnalisé (à partir de "PlayerModel.scn") reste sur l'ancre de l'avion:

wrapperNode.position = SCNVector3.positionFromTransform(anchor.transform)
wrapperNode.addChildNode(Body)
scnView.scene.rootNode.addChildNode(wrapperNode)

Ce code utilise la position initiale de l'ancre plane pour positionner wrapperNode dans l'espace mondial (car vous en faites un enfant du nœud racine). Si vous faites plutôt de wrapperNode un enfant du nœud d'ancrage de l'avion (celui que vous avez reçu dans renderer(_:didAdd:for:)), il restera attaché à l'avion pendant qu'ARKit affine son estimation de la position de l'avion. Vous obtiendrez un peu plus de mouvement au départ, mais au fur et à mesure que la détection d'avion "s'installe", votre objet virtuel "glissera" moins.

(Lorsque vous faites du nœud un enfant de l'avion, vous n'avez pas besoin de définir sa position - une position de zéro signifie qu'il est juste là où se trouve l'avion. Inf quoi que ce soit, vous devez définir sa position uniquement par rapport à l'avion - c'est-à-dire à quelle distance au-dessus/en dessous/le long de celui-ci.)

27
rickster