我正在尝试计算特定几何点ARFaceGeometry
/ ARFaceAnchor
上SpriteKit覆盖内容的位置(而不仅仅是覆盖视觉内容)。
我从计算出的世界坐标中使用SCNSceneRenderer.projectPoint
,但是结果是y反转并且未与相机图像对齐:
let vertex4 = vector_float4(0, 0, 0, 1)
let modelMatrix = faceAnchor.transform
let world_vertex4 = simd_mul(modelMatrix, vertex4)
let pt3 = SCNVector3(x: Float(world_vertex4.x),
y: Float(world_vertex4.y),
z: Float(world_vertex4.z))
let sprite_pt = renderer.projectPoint(pt3)
// To visualize sprite_pt
let dot = SKSpriteNode(imageNamed: "dot")
dot.size = CGSize(width: 7, height: 7)
dot.position = CGPoint(x: CGFloat(sprite_pt.x),
y: CGFloat(sprite_pt.y))
overlayScene.addChild(dot)
答案 0 :(得分:2)
根据我的经验,ARKit的projectPoint
函数给出的屏幕坐标在绘制到CALayer
时可以直接使用。这意味着它们遵循here中所述的iOS坐标,其中原点位于左上角,y取反。
SpriteKit具有its own coordinate system:
单位坐标系将原点放置在框架的左下角,将(1,1)放置在框架的右上角。精灵的锚点默认为(0.5,0.5),与框架的中心相对应。
最后,将SKNode放置在SKScene中,其起源在左下角。您应该确保您的SKScene与您的实际视图大小相同,否则原点可能不在视图的左下角,因此您在视图中对节点的定位可能不正确。 this question的答案可能会有所帮助,特别是检查视图的AspectFit或AspectFill以确保场景按比例缩小。
场景的原点位于左下角,具体取决于您的场景大小和缩放比例,它可能不在屏幕上。这是0,0所在的位置。因此,您添加的每个孩子都会从那里开始,并根据位置正确地向上工作。 SKSpriteNode的原点位于中心。
因此,从视图坐标和SpriteKit坐标进行转换的两个基本步骤是:1)反转y轴,使原点位于左下角; 2)确保您的SKScene框架与视图框架匹配。
我可以稍作测试,然后编辑是否存在任何问题
答案 1 :(得分:0)
找到了使用camera.projectPoint而不是renderer.projectPoint的转换。
要在spritekit上正确缩放点:设置scaleMode = .aspectFill
我更新了https://github.com/AnsonT/ARFaceSpriteKitMapping进行了演示。
guard let faceAnchor = anchor as? ARFaceAnchor,
let camera = sceneView.session.currentFrame?.camera,
let sie = overlayScene?.size
else { return }
let modelMatrix = faceAnchor.transform
let vertices = faceAnchor.geometry.vertices
for vertex in vertices {
let vertex4 = vector_float4(vertex.x, vertex.y, vertex.z, 1)
let world_vertex4 = simd_mul(modelMatrix, vertex4)
let world_vector3 = simd_float3(x: world_vertex4.x, y: world_vertex4.y, z: world_vertex4.z)
let pt = camera.projectPoint(world_vector3, orientation: .portrait, viewportSize: size)
let dot = SKSpriteNode(imageNamed: "dot")
dot.size = CGSize(width: 7, height: 7)
dot.position = CGPoint(x: CGFloat(pt.x), y: size.height - CGFloat(pt.y))
overlayScene?.addChild(dot)
}