我正在开发一个iOS应用程序,目前正在尝试获取AR体验中旋转的SCNNode的4个顶点的坐标(参考世界/根节点
从我调试这个乱七八糟的东西来看,旋转和倾斜的SCNPlane的边界框仍然与世界原点保持一致。
我已经在this线程中尝试过这个解决方案。
我试图探测的飞机直接放在ARKit探测到的图像上:
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
guard let imageAnchor = anchor as? ARImageAnchor else { return }
let referenceImage = imageAnchor.referenceImage
updateQueue.async {
// Create a plane to visualize the initial position of the detected image.
let plane = SCNPlane(width: referenceImage.physicalSize.width,
height: referenceImage.physicalSize.height)
let planeNode = SCNNode(geometry: plane)
planeNode.opacity = 0.25
/*
`SCNPlane` is vertically oriented in its local coordinate space, but
`ARImageAnchor` assumes the image is horizontal in its local space, so
rotate the plane to match.
*/
planeNode.eulerAngles.x = -.pi / 2
/*
Image anchors are not tracked after initial detection, so create an
animation that limits the duration for which the plane visualization appears.
*/
planeNode.runAction(self.imageHighlightAction)
// This is where I tried to calculate the edge
let (min, max) = planeNode.boundingBox
let topLeft = SCNVector3(min.x, max.y, 0)
let worldTopLeft = planeNode.convertPosition(topLeft, to: self.sceneView.scene.rootNode)
let world2dTopLeft = self.sceneView.projectPoint(worldTopLeft)
node.addChildNode(planeNode)
}
}预期的结果是屏幕上的某种2D位置,在3D视图中直接位于角落的顶部,但我总是得到巨大的数字,如x: 8847.291, y: -10651.121
有谁有解决这个问题的办法吗?
发布于 2019-04-24 19:11:20
好了,我找到了解决方案:
我需要通过一些高级数学来计算,你们中的一些人可能比我解释得更好。
工作副本(适用于Swift 4.2)为:
let imageAnchor: ARImageAnchor! // provided by renderer()
let scale: CGFloat! // UIDevice.main.scale (device scale)
// returns a transform matrix from a point
let imageTransform: (_ x: CGFloat, _ y: CGFloat) -> float4x4 = {x, y in
var tf = float4x4(diagonal: float4(repeating: 1))
tf.columns.3 = float4(x: Float(x), y: 0, z: Float(y), w: 1)
return tf
}
let imageSize = imageAnchor.referenceImage.physicalSize
let worldTransform = imageAnchor.transform
let topLeft = imageTransform(-imageSize.width / 2, -imageSize.height / 2)
let topRight = imageTransform(imageSize.width / 2, -imageSize.height / 2)
let bottomLeft = imageTransform(-imageSize.width / 2, imageSize.height / 2)
let bottomRight = imageTransform(imageSize.width / 2, imageSize.height / 2)
let transformTopLeft = worldTransform * topLeft
let transformTopRight = worldTransform * topRight
let transformBottomLeft = worldTransform * bottomLeft
let transformBottomRight = worldTransform * bottomRight
let pointTopLeft = self.sceneView.projectPoint(SCNVector3(x: transformTopLeft.columns.3.x,
y: transformTopLeft.columns.3.y,
z: transformTopLeft.columns.3.z))
let pointTopRight = self.sceneView.projectPoint(SCNVector3(x: transformTopRight.columns.3.x,
y: transformTopRight.columns.3.y,
z: transformTopRight.columns.3.z))
let pointBottomLeft = self.sceneView.projectPoint(SCNVector3(x: transformBottomLeft.columns.3.x,
y: transformBottomLeft.columns.3.y,
z: transformBottomLeft.columns.3.z))
let pointBottomRight = self.sceneView.projectPoint(SCNVector3(x: transformBottomRight.columns.3.x,
y: transformBottomLeft.columns.3.y,
z: transformBottomLeft.columns.3.z))
// Those are the CGPoints, projected to the screen
let cgTL = CGPoint(x: CGFloat(pointTopLeft.x)*scale, y: extent.height-CGFloat(pointTopLeft.y)*scale)
let cgTR = CGPoint(x: CGFloat(pointTopRight.x)*scale, y: extent.height-CGFloat(pointTopRight.y)*scale)
let cgBL = CGPoint(x: CGFloat(pointBottomLeft.x)*scale, y: extent.height-CGFloat(pointBottomLeft.y)*scale)
let cgBR = CGPoint(x: CGFloat(pointBottomRight.x)*scale, y: extent.height-CGFloat(pointBottomRight.y)*scale)这一切都运行得很好。我希望有人能解释一下我在那里做了什么。
发布于 2019-04-24 18:18:13
从局部空间变换到世界空间时,不应将z位置设置为零。您可以使用边界框min和max值,而无需修改它们:
let (min, max) = planeNode.boundingBox
// local space to world space
let minWorld = planeNode.convertPosition(min, to: self.sceneView.scene.rootNode)
let maxWorld = planeNode.convertPosition(max, to: self.sceneView.scene.rootNode)
// world space to screen space
let minScreen = self.sceneView.projectPoint(minWorld)
let maxScreen = self.sceneView.projectPoint(maxWorld)然后,您可以使用minScreen和maxScreen的x和y坐标并忽略z。
https://stackoverflow.com/questions/55728415
复制相似问题