Using both horizontal and vertical planes in ARKit / RealityKit
ARKit 5.0
You can do it as usually, using the habitual approach:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
let configuration = ARWorldTrackingConfiguration()
configuration.planeDetection = [.horizontal, .vertical]
arView.session.run(configuration)
}
planeDetection
instance property is gettable and settable:
var planeDetection: ARWorldTrackingConfiguration.PlaneDetection { get set }
...and PlaneDetection
struct conforms to OptionSet protocol which allows you to use just a single value or both values at the same time:
configuration.planeDetection = []
configuration.planeDetection = .vertical
configuration.planeDetection = [.horizontal, .vertical]
Then add renderer(_:didAdd:for:) instance method to your code that might look like this:
func renderer(_ renderer: SCNSceneRenderer,
didAdd node: SCNNode,
for anchor: ARAnchor) {
guard let planeAnchor = anchor as? ARPlaneAnchor
else { return }
let width = CGFloat(planeAnchor.extent.x)
let height = CGFloat(planeAnchor.extent.z)
let myPlane = SCNPlane(width: width, height: height)
if planeAnchor.alignment == .horizontal {
myPlane.materials.first?.diffuse.contents = UIColor.semiOpaqueRed
} else if planeAnchor.alignment == .vertical {
myPlane.materials.first?.diffuse.contents = UIColor.semiOpaqueCyan
}
let planeNode = SCNNode(geometry: myPlane)
let x = CGFloat(planeAnchor.center.x)
let y = CGFloat(planeAnchor.center.y)
let z = CGFloat(planeAnchor.center.z)
planeNode.position = SCNVector3(x, y, z)
planeNode.eulerAngles.x = -.pi / 2
node.addChildNode(planeNode)
}
And, at last, add renderer(_:didUpdate:for:) instance method that might look like this:
func renderer(_ renderer: SCNSceneRenderer,
didUpdate node: SCNNode,
for anchor: ARAnchor) {
guard let planeAnchor = anchor as? ARPlaneAnchor,
let planeNode = node.childNodes.first,
let myPlane = planeNode.geometry as? SCNPlane
else { return }
let width = CGFloat(planeAnchor.extent.x)
let height = CGFloat(planeAnchor.extent.z)
myPlane.width = width
myPlane.height = height
let x = CGFloat(planeAnchor.center.x)
let y = CGFloat(planeAnchor.center.y)
let z = CGFloat(planeAnchor.center.z)
planeNode.position = SCNVector3(x, y, z)
}
RealityKit 2.0
It only takes a few lines of code to implement this idea in RealityKit.
let arView = ARView(frame: .zero)
let model = try! ModelEntity.load(named: "Model.usdz")
let anchor = AnchorEntity(plane: [.horizontal, .vertical],
classification: [.floor, .wall],
minimumBounds: [0.5, 0.5])
anchor.addChild(model)
arView.scene.anchors.append(anchor)
How to detect vertical planes in ARKit?
Edit: This is now supported as of ARKit 1.5 (iOS 11.3). Simply use .vertical
. I have kept the previous post below for historical purposes.
TL;DR
Vertical plane detection is not (yet) a feature that exists in ARKit. The .horizontal
suggests that this feature could be being worked on and might be added in the future. If it was just a Boolean value, this would suggest that it is final.
Confirmation
This suspicion was confirmed by a conversation that I had with an Apple engineer at WWDC17.
Explanation
You could argue that creating an implementation for this would be difficult as there are infinitely many more orientations for a vertical plane rather than a horizontal one, but as rodamn said, this is probably not the case.
From rodamn’s comment:
At its simplest, a plane is defined to be three coplanar points. You have a surface candidate once there are sufficient detected coplanar features detected along a surface (vertical, horizontal, or at any arbitrary angle). It's just that the normal for horizontals will be along the up/down axis, while vertical's normals will be parallel to the ground plane. The challenge is that unadorned drywall tends to generate few visual features, and plain walls may often go undetected. I strongly suspect that this is why the .vertical
feature is not yet released.
However, there is a counter argument to this. See comments from rickster for more information.
ARFoundation detecting vertical planes and placing objects - Unity
ARFoundation 1.0.0 preview 22 will surface the ability to select your plane detection mode: horizontal, vertical, or both. To use this mode, you will have to upgrade to the newly released Unity 2018.3: https://blogs.unity3d.com/2018/12/13/introducing-unity-2018-3/
For more about plane detection in ARFoundation, refer the following link
AR Plane Manager
Related Topics
Programmatically Creating Constraints Bound to View Controller Margins
How Set Rootviewcontroller in Scene Delegate iOS 13
Implementing Nscopying in Swift with Subclasses
Grab Frames from Video Using Swift
Checking If Textfields Are Empty Swift
"Cannot Assign Value of Type 'String' to Type 'Anyobject'", Swift 3, Xcode 8 Beta 6
How to Change the Associated Values of a Enum
In Swiftui, Where Are the Control Events, I.E. Scrollviewdidscroll to Detect the Bottom of List Data
Get Image from Calayer or Nsview (Swift 3)
Background Request Not Execute Alamofire Swift
Back Button Image - What Is It Called in Swift
Two Tables on One View in Swift
How to Open Your App in Settings iOS 11
How to Disable Vertical Scroll in Tabview with Swiftui
How to Implement Copy Constructor in Swift Subclass
What's the Difference Between Using or Not Using the 'Where' Clause with Generics