À propos du curseur à afficher lors du placement d'un objet arbitraire dans AR.
Ceci est une application de mesure standard.
Effectuez un test de succès sur les coordonnées centrales de l'écran et définissez-les en fonction du worldTransform
acquis.
Puisque l'emplacement atteint par hitTest (_: types:)
de ʻARSCNView peut être obtenu à partir de
worldTransform de ʻARHitTestResult
, il est utilisé comme emplacement et orientation du curseur.
Ici, lorsque le curseur est réglé sur SCNPlane
, si l'emplacement / l'orientation du curseur = l'emplacement / l'orientation de la frappe, il interfère avec la géométrie du plan et scintille, donc le vecteur ascendant de l'avionworldTransform.columns.1 Utilisez
pour ajuster la position du curseur.
//0 dans la direction (HAUT) face au plan.Placez le curseur sur une position décalée de 01m
cursorTransform.columns.3 += worldTransform.columns.1 * 0.01
self.cursorNode.simdTransform = cursorTransform
Notez que la mise à l'échelle est réinitialisée si le SCNNode
est mis à l'échelle ( scale
≠ (1.0,1.0,1.0)) car la transformation est définie.
Dans ce cas, définissez la valeur obtenue en multipliant worldTransform.columns.0 ~ 2 par le rapport de mise à l'échelle sur cursorTransform.columns.0 ~ 2.
Il a une forme pyramidale de sorte que la direction ascendante du curseur peut être facilement comprise.
Code source
ViewController.swift
import ARKit
import SceneKit
class ViewController: UIViewController, ARSCNViewDelegate {
@IBOutlet weak var scnView: ARSCNView!
private let device = MTLCreateSystemDefaultDevice()!
private let cursorNode = SCNNode()
override func viewDidLoad() {
super.viewDidLoad()
//Session AR démarrée
self.scnView.delegate = self
let configuration = ARWorldTrackingConfiguration()
configuration.planeDetection = [.horizontal, .vertical]
self.scnView.session.run(configuration, options: [.removeExistingAnchors, .resetTracking])
//Préparation du nœud de curseur
let pyramid = SCNPyramid(width: 0.1, height: 0.03, length: 0.1)
pyramid.firstMaterial!.diffuse.contents = UIColor.yellow
self.cursorNode.geometry = pyramid
self.scnView.scene.rootNode.addChildNode(self.cursorNode)
self.cursorNode.isHidden = true
}
//
//Ancre ajoutée
//
func renderer(_: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
guard let planeAnchor = anchor as? ARPlaneAnchor else { return }
//Ajout d'un nœud de géométrie plane
guard let geometory = ARSCNPlaneGeometry(device: self.device) else { return }
geometory.update(from: planeAnchor.geometry)
let material = SCNMaterial()
material.lightingModel = .physicallyBased
material.diffuse.contents = UIColor.red.withAlphaComponent(0.7)
geometory.materials = [material]
let planeNode = SCNNode(geometry: geometory)
DispatchQueue.main.async {
node.addChildNode(planeNode)
}
}
//
//Ancre mise à jour
//
func renderer(_: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
guard let planeAnchor = anchor as? ARPlaneAnchor else { return }
DispatchQueue.main.async {
for childNode in node.childNodes {
//Mettre à jour la géométrie du plan
guard let planeGeometry = childNode.geometry as? ARSCNPlaneGeometry else { continue }
planeGeometry.update(from: planeAnchor.geometry)
break
}
}
}
//
//Appelé image par image
//
func renderer(_ renderer: SCNSceneRenderer, updateAtTime _: TimeInterval) {
DispatchQueue.main.async {
//Hit test au centre de l'écran
let bounds = self.scnView.bounds
let screenCenter = CGPoint(x: bounds.midX, y: bounds.midY)
let results = self.scnView.hitTest(screenCenter, types: [.existingPlaneUsingGeometry])
guard let existingPlaneUsingGeometryResult = results.first(where: { $0.type == .existingPlaneUsingGeometry }),
let _ = existingPlaneUsingGeometryResult.anchor as? ARPlaneAnchor else {
//Masquer le curseur
self.cursorNode.isHidden = true
return
}
//Publier la transformation de l'emplacement du hit à la transformation du curseur
let worldTransform = existingPlaneUsingGeometryResult.worldTransform
var cursorTransform = worldTransform
//0 dans la direction (HAUT) face au plan.Placez le curseur sur une position décalée de 01m
cursorTransform.columns.3 += worldTransform.columns.1 * 0.01
self.cursorNode.simdTransform = cursorTransform
self.cursorNode.isHidden = false
}
}
}
Recommended Posts