我想获取ARKit已识别到ARSCNView
屏幕坐标的平面的角坐标。
我开始使用Apple的例子来创建飞机,所以我有一个飞机课程:
class Plane : SCNNode {
var anchor : ARPlaneAnchor
init(anchor : ARPlaneAnchor) {
self.anchor = anchor
super.init()
self.geometry = SCNPlane(width: CGFloat(Float(anchor.extent.x)), height: CGFloat(anchor.extent.z))
self.rotation = SCNVector4Make(1.0, 0.0, 0.0, -Float.pi/2.0)
let material = SCNMaterial()
material.diffuse.contents = UIColor.yellow
material.specular.contents = UIColor.white
self.geometry?.firstMaterial = material
}
required init?(coder aDecoder: NSCoder) {
fatalError("Error")
}
func update(anchor: ARPlaneAnchor) {
self.anchor = anchor
if let plane = self.geometry as? SCNPlane {
plane.width = CGFloat(anchor.extent.x)
plane.height = CGFloat(anchor.extent.z)
}
}
}
视图控制器中的ARSCNViewDelegate方法用于识别和更新它:
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
if let planeAnchor = anchor as? ARPlaneAnchor {
let plane = Plane(anchor: planeAnchor)
node.addChildNode(plane)
planes[planeAnchor] = plane
print("plane = \(plane)")
}
}
func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
if let planeAnchor = anchor as? ARPlaneAnchor {
planes[planeAnchor]?.update(anchor: planeAnchor)
}
}
func renderer(_ renderer: SCNSceneRenderer, didRemove node: SCNNode, for anchor: ARAnchor) {
if let planeAnchor = anchor as? ARPlaneAnchor {
planes.removeValue(forKey: planeAnchor)
}
}
据我了解,该平面在SceneKit中拥有自己的局部坐标空间,所以我想创建4个SCNVector3
值,并将它们从Plane的局部空间转换到场景的世界坐标空间,然后将它们投射到屏幕的空间。
我正是这样做的:
func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {
for (_, aPlane) in planes {
// Vectors representing the corners of the plane
let maxX = aPlane.anchor.extent.x/2.0
let minX = -maxX
let minY = aPlane.anchor.extent.z/2.0
let maxY = -minY
var point1 = SCNVector3Make(minX, 0.0, minY)
var point2 = SCNVector3Make(maxX, 0.0, minY)
var point3 = SCNVector3Make(maxX, 0.0, maxY)
var point4 = SCNVector3Make(minX, 0.0, maxY)
// var point1 = SCNVector3Make(minX, minY, 0.0)
// var point2 = SCNVector3Make(maxX, minY, 0.0)
// var point3 = SCNVector3Make(maxX, maxY, 0.0)
// var point4 = SCNVector3Make(minX, maxY, 0.0)
print("initial nodes ------------------")
print("point1 = \(point1)")
print("point2 = \(point2)")
print("point3 = \(point3)")
print("point4 = \(point4)")
// Get the root node and convert the coords from the plane's coord system
let rootNode = sceneView.scene.rootNode
point1 = rootNode.convertVector(point1, from: aPlane)
point2 = rootNode.convertVector(point2, from: aPlane)
point3 = rootNode.convertVector(point3, from: aPlane)
point4 = rootNode.convertVector(point4, from: aPlane)
print("first conversion nodes ------------------")
print("point1 = \(point1)")
print("point2 = \(point2)")
print("point3 = \(point3)")
print("point4 = \(point4)")
// Finally, project them to the screen view
point1 = sceneView.projectPoint(point1)
point2 = sceneView.projectPoint(point2)
point3 = sceneView.projectPoint(point3)
point4 = sceneView.projectPoint(point4)
print("final conversion nodes ------------------")
print("point1 = \(point1)")
print("point2 = \(point2)")
print("point3 = \(point3)")
print("point4 = \(point4)")
}
}
但是,无论我做什么,当我在全视图中有一架飞机时,我仍然可以获得超出视图范围的坐标。我很确定它很简单,但我现在尝试了很多组合。