Я работаю с приложением 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
узла, но это не привело к видимым изменениям объекта.