Comment puis-je utiliser les plans horizontaux et verticaux suivis par ARKit pour cacher des objets derrière des murs/derrière de vrais objets? Actuellement, les objets ajoutés en 3D peuvent être vus à travers les murs lorsque vous quittez une pièce et/ou devant des objets qu'ils devraient être derrière. Est-il donc possible d'utiliser les données fournies par ARKit pour offrir une expérience de RA plus naturelle sans que les objets apparaissent à travers les murs?
Vous avez deux problèmes ici.
(Et vous n'avez même pas utilisé des expressions régulières !)
Si vous définissez le paramètre colorBufferWriteMask
d'un matériau SceneKit sur une valeur vide ([]
dans Swift), les objets utilisant ce matériau n'apparaîtront pas dans la vue, mais ils continueront à écrire dans le tampon z lors du rendu, ce qui affectera le rendu d'autres objets. En réalité, vous obtiendrez un "trou" en forme de votre objet, à travers lequel apparaît l'arrière-plan (le flux de la caméra, dans le cas de ARSCNView
), mais qui peut encore masquer d'autres objets SceneKit.
Vous devrez également vous assurer qu'un rendu masqué est rendu avant tout autre nœud qu'il est supposé masquer. Vous pouvez le faire en utilisant la hiérarchie des noeuds (je ne me souviens pas immédiatement si les noeuds parents sont rendus avant leurs enfants ou l'inverse, mais c'est assez facile à tester). Les nœuds homologues de la hiérarchie n'ont pas d'ordre déterministe, mais vous pouvez forcer un ordre quelle que soit la hiérarchie avec la propriété renderingOrder
. La valeur par défaut de cette propriété est zéro. Par conséquent, la valeur -1 rend le rendu avant tout. (Ou pour un contrôle plus précis, définissez la valeur renderingOrder
s de plusieurs nœuds sur une séquence de valeurs.)
Dans iOS 11.3 et versions ultérieures ("ARKit 1.5"), vous pouvez activer la détection vertical
plane. (Notez que lorsque vous récupérez les ancres vertical
, elles sont automatiquement pivotées. Ainsi, si vous associez des modèles à l'ancre, leur direction locale "en haut" est normale par rapport au plan.) Nouveau également dans iOS 11.3 , vous pouvez obtenir une estimation de forme plus détaillée pour chaque plan détecté (voir ARSCNPlaneGeometry ), quelle que soit son orientation.
Cependant, même si vous avez l'horizontale et la verticale, les limites extérieures d'un plan ne sont que des estimations qui changent avec le temps. C'est-à-dire qu'ARKit peut rapidement localiser une partie d'un mur, mais il ne sait pas où sont les bords du mur sans que l'utilisateur passe du temps à agiter le périphérique pour cartographier l'espace. Et même dans ce cas, les bords cartographiés pourraient ne pas être alignés avec ceux du vrai mur.
Donc ... si vous utilisez des plans verticaux détectés pour obstruer une géométrie virtuelle, vous pouvez trouver des endroits où les objets virtuels censés être cachés sont visibles, soit en ne se cachant pas tout à fait au bord du mur, soit en étant visibles à travers des endroits. où ARKit n’a pas cartographié l’ensemble du vrai mur. (Ce dernier problème pourrait être résolu en supposant une plus grande étendue que ne le fait ARKit.)
Excellente solution:
Travaillé pour moi.
Mais dans mon cas, je voulais définir les murs par code. Donc, si vous ne voulez pas définir les murs par utilisateur -> utilisez la détection de plan pour détecter les murs et les définir par code.
Ou dans une portée de 4 mètres, le capteur de profondeur iPhone fonctionne et vous pouvez détecter des obstacles avec ARHitTest .
Pour les opérations en attente (trou noir ou matériau bloquant, par exemple), vous pouvez utiliser la propriété d'instance, appelée .colorBufferWriteMask
, dans iOS 11 et macOS 13. Cette propriété écrit des informations de canal de profondeur lors du rendu du matériau. Vous pouvez l'utiliser de cette façon:
torus.geometry?.firstMaterial?.colorBufferWriteMask = .alpha
ou de cette façon:
func blockingMaterial() -> SCNMaterial {
let holdout = SCNMaterial()
holdout.isDoubleSided = true
holdout.diffuse.contents = CIColor.black
holdout.colorBufferWriteMask = SCNColorMask(rawValue: 0)
return holdout
}
torus.geometry?.firstMaterial = blockingMaterial()
Vous pouvez facilement utiliser cette propriété pour ombrer vos murs virtuels invisibles. Pour positionner ces murs virtuels invisibles au bon endroit, aidez ARWorldMap
class (cela fonctionne sous iOS 12) et ARAnchors
.
session.getCurrentWorldMap { worldMap, error in
guard let worldMap = worldMap else {
showAlert(error)
return
}
}
let configuration = ARWorldTrackingConfiguration()
configuration.initialWorldMap = worldMap
session.run(configuration)
ARWorldMap
est l’état de mappage d’espace et l’ensemble des ARAnchors d’une session d’AR de suivi du monde. Lire à ce sujet ici .
Pour créer un matériau d'occlusion, c'est très simple
let boxGeometry = SCNBox(width: 0.1, height: 0.1, length: 0.1, chamferRadius: 0)
// Define a occlusion material
let occlusionMaterial = SCNMaterial()
occlusionMaterial.colorBufferWriteMask = []
boxGeometry.materials = [occlusionMaterial]
self.box = SCNNode(geometry: boxGeometry)
// Set rendering order to present this box in front of the other models
self.box.renderingOrder = -1