Выравнивание ARFaceAnchor с наложением SpriteKit - PullRequest
0 голосов
/ 06 ноября 2018

Я пытаюсь вычислить положение наложенного содержимого SpriteKit (а не только наложение визуального содержимого) на определенные геометрические точки ARFaceGeometry / ARFaceAnchor.

Я использую SCNSceneRenderer.projectPoint из вычисленной мировой координаты, но результат у инвертирован и не выровнен по изображению с камеры:

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)

Ответы [ 2 ]

0 голосов
/ 14 ноября 2018

Найдено преобразование, которое работает с использованием camera.projectPoint вместо renderer.projectPoint.

Чтобы правильно масштабировать точки на спрайтеките: установите 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)

    }
0 голосов
/ 07 ноября 2018

По моему опыту, экранные координаты, заданные функцией projectPoint ARKit, могут непосредственно использоваться при рисовании, например, в CALayer. Это означает, что они следуют координатам iOS, как описано здесь , где начало координат находится в верхнем левом углу, а y инвертировано.

SpriteKit имеет свою собственную систему координат :

Система координат единицы размещает начало координат в нижнем левом углу рамки и (1,1) в верхнем правом углу рамки. По умолчанию точка привязки спрайта равна (0,5,0,5), что соответствует центру кадра.

Наконец, SKNodes помещаются в SKScene, источник которого находится слева внизу. Вы должны убедиться, что ваш SKScene имеет тот же размер, что и ваш фактический вид, иначе источник может быть не в левом нижнем углу вида, и, таким образом, ваше расположение узла по координатам представления может быть неверным. Ответ на этот вопрос может помочь, в частности, проверка AspectFit или AspectFill вашего представления, чтобы убедиться, что ваша сцена сокращается.

Источник сцены находится внизу слева и, в зависимости от размера сцены и ее масштабирования, может находиться за пределами экрана. Это где 0,0. Таким образом, каждый ребенок, которого вы добавите, начнет там и будет работать правильно и в зависимости от положения. SKSpriteNode имеет свое происхождение в центре.

Таким образом, два основных шага для преобразования из координат вида и координат SpriteKit будут: 1) инвертировать ось Y, чтобы исходная точка находилась слева внизу, и 2) убедиться, что ваш кадр SKScene соответствует вашему кадру обзора.

Я могу немного подробнее проверить это и отредактировать, если возникнут проблемы

...