2017-10-20 28 views
0

J'ai plusieurs nœuds dans ma scène que je peux faire pivoter et faire glisser. J'ai mis en place un délégué physicsWorld, ajouté physicsBody avec le type cinématique à mes noeuds et je vérifie pour physicsWorld didBeginContact - jusqu'ici tout est ok, quand je déplace les noeuds, le contact commence/termine le feu. La façon dont j'essaye de gérer cela est de définir un var bool qui passe à vrai une fois que le contact commence à empêcher tout mouvement, mais je cours dans des cas (surtout si je fais glisser le noeud trop vite), que le nœud se trouve un peu à l'intérieur de l'autre objet.Scenekit - Configuration de physicsWorld pour empêcher les nœuds cinématiques de se croiser

devrais-je utiliser une approche différente à ce sujet? Je ne veux pas vraiment une collision, juste l'autre nœud pour agir "solide" et ne pas permettre l'intersection même à un contact à vitesse plus élevée.

EDIT:

Quelques exemples d'images afin de clarifier davantage la question:

Pour simplifier, j'ai ajouté seulement deux noeuds pour démontrer la question. La première image est la position initiale, la 2e et la 3e (vue de côté) sont après un panoramique très rapide vers la droite. La détection de contact a été déclenchée seulement après l'intersection des nœuds. Une approche que j'ai essayée était d'attraper la dernière position avant que le contact soit déclenché et de rétablir la position de noeud après que le contact soit détecté, mais le résultat est très instable et instable et pendant une fraction de seconde vous pouvez voir les objets se croiser quand même avant de sauter à la dernière "bonne" position. Je pense qu'il doit y avoir un moyen plus facile d'y parvenir, mais après avoir passé des heures à parcourir les ressources disponibles, je ne peux pas le comprendre.

EDIT 2

des recherches plus poussées a la ligne de test de balayage, techniquement si je peux détecter une collision possible avant de passer le nœud, je devrais être en mesure de limiter le mouvement à arrêter avant le intersetion se produit

MISE à JOUR: une autre impasse, comme Xcode souligne

Error: convexSweep only works with convex shapes 

Répondre

1

Après beaucoup de jours de headbanger et al la plupart abandonnant, je relisais de nouveau la documentation de physicsWorld et finalement trouvais ce que je voyais tout le temps - la méthode contactTest qui peut être déclenchée manuellement à tout moment, indépendamment de la boucle de rendu. Je l'utilise dans le renderer (_: willRenderScene: atTime :) pour "réparer" le chevauchement avant que la scène ne soit rendue.

Ma scène est un peu plus compliquée que l'exemple, mais avec quelques tweeks supplémentaires je l'ai presque fonctionné maintenant. Je ne suis pas sûr que ce soit la bonne solution et à quel point cela deviendra cher en termes de performance, mais pour l'instant je vais m'installer avec ça afin que je puisse avancer dans le développement.

Le code correspondant dans cas où quelqu'un va dans la même situation:

func renderer(_ renderer: SCNSceneRenderer, willRenderScene scene: SCNScene, atTime time: TimeInterval) { 

    // make sure we have active node and pan direction 
    if(selectedBrickNode != nil && self.panDirection != nil){ 

     // contactTest 
     let pw = scnScene.physicsWorld 
     let node = selectedBrickNode.node! 
     let contacts = pw.contactTest(with: node.physicsBody!, options: nil) 

     var axisVector:SCNVector3 
     // specify which axis we want to correct 
     switch self.panDirection!{ 
      case "right","left": axisVector = SCNVector3Make(1,0,0) 
      default: axisVector = SCNVector3Make(0,1,0); 
     } 

     for contact in contacts { 
      // round contact normal to get a unit vector 
      let cn = SCNVector3(round(contact.contactNormal.x), 
           round(contact.contactNormal.y), 
           round(contact.contactNormal.z)) 

      // fix only for pan direction axis 
      if abs(cn.x) == axisVector.x && abs(cn.y)==axisVector.y { 
       let normal = contact.contactNormal 
       let transform = SCNMatrix4MakeTranslation(round(normal.x) * -Float(contact.penetrationDistance), 
              round(normal.y) * -Float(contact.penetrationDistance), 
              round(normal.z) * -Float(contact.penetrationDistance)) 
       node.transform = SCNMatrix4Mult(node.transform, transform) 
       // break to prevent repeated contacts 
       break; 
      } 

     } 

    } 
}