Применить несколько поворотов к ARKit SCNNode - PullRequest
0 голосов
/ 08 января 2019

Я работаю с приложением AR, которое использует Apple Focus Square, чтобы направлять взаимодействие пользователя как на вертикальной, так и на горизонтальной поверхностях. Тем не менее, он предназначен только для работы на горизонтальных поверхностях. Я изменил метод, который обновляет вращение квадрата, чтобы учесть также вертикальные поверхности. Однако, используя метод, в котором они использовали только одно вращение, можно выполнять одновременно, тогда как для правильного расположения квадрата на горизонтальной поверхности мне нужно выполнить два вращения (одно, чтобы применить исходную коррекцию рыскания, и одно, чтобы наклоните квадрат вертикально).

Соответствующий код приведен ниже, но конкретные изменения, которые я сделал, только в начале и в конце.

// MARK: - Appearence

func update(for position: float3, planeAnchor: ARPlaneAnchor?, camera: ARCamera?) {
    lastPosition = position

    let thisAlignment = planeAnchor?.alignment ?? .horizontal
    if thisAlignment != lastAlignment {
        lastAlignment = thisAlignment
        print("alignmentChanged")
        recentFocusSquarePositions = []
    }

    if let anchor = planeAnchor {
        close(flash: !anchorsOfVisitedPlanes.contains(anchor))
        lastPositionOnPlane = position
        anchorsOfVisitedPlanes.insert(anchor)
    } else {
        open()
    }
    updateTransform(for: position, alignment: thisAlignment, camera: camera)
}

private func updateTransform(for position: float3, alignment: ARPlaneAnchor.Alignment, camera: ARCamera?) {
    // add to list of recent positions
    recentFocusSquarePositions.append(position)

    // remove anything older than the last 8
    recentFocusSquarePositions.keepLast(8)

    // move to average of recent positions to avoid jitter
    if let average = recentFocusSquarePositions.average {
        self.simdPosition = average
        self.setUniformScale(scaleBasedOnDistance(camera: camera))
    }

    // Correct y rotation of camera square
    if let camera = camera {
        let tilt = abs(camera.eulerAngles.x)
        let threshold1: Float = .pi / 2 * 0.65
        let threshold2: Float = .pi / 2 * 0.75
        let yaw = atan2f(camera.transform.columns.0.x, camera.transform.columns.1.x)
        var angle: Float = 0

        switch tilt {
        case 0..<threshold1:
            angle = camera.eulerAngles.y
        case threshold1..<threshold2:
            let relativeInRange = abs((tilt - threshold1) / (threshold2 - threshold1))
            let normalizedY = normalize(camera.eulerAngles.y, forMinimalRotationTo: yaw)
            angle = normalizedY * (1 - relativeInRange) + yaw * relativeInRange
        default:
            angle = yaw
        }

        if alignment == .vertical{
            self.rotation = SCNVector4(0, 1, 1, Float.pi)
        } else {
            self.rotation = SCNVector4(0, 1, 0, angle)
        }
    }
}

Моя цель состоит в том, чтобы оба поворота в операторе управления в конце выполнялись на объекте. Если оператор else удален, применяется только это вращение, а квадрат остается горизонтальным. Я попытался сделать обе модификации преобразования напрямую, используя SCNMatrix4MakeRotation(_:_:_:_:), но это привело к тому, что квадрат вращался бесконечно и позиционировался неправильно. Я также попытался настроить Pivot узла, но это не привело к видимым изменениям объекта.

...