首页 > 解决方案 > 对 ARKit SCNNode 应用多次旋转

问题描述

我正在使用一个 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,但这导致对象没有可见的变化。

标签: swiftscenekitlinear-algebraarkit

解决方案


推荐阅读