В настоящее время я сталкиваюсь с проблемой, заключающейся в том, что я хочу вычислить угол в радианах от положения камеры до целевого положения.Однако этот расчет должен учитывать и направление камеры.
Например, когда камера направлена в сторону от объекта, функция должна возвращать π.Пока что функция, которую я написал, работает большую часть времени.Однако, когда пользователь приближается к осям X и Z, стрелка больше не указывает на цель, скорее она слегка указывает влево или вправо, в зависимости от того, находятся ли вы в положительном или отрицательном положении X и z.
В настоящее время я не уверен, почему моя функция не работает.Единственное объяснение такого поведения - фиксация карданного подвеса.Однако я не совсем уверен, как реализовать ту же функцию с помощью кватернионов.
Я также приложил несколько фотографий к этому сообщению, что проблема немного яснее.
Вот функцияЯ использую прямо сейчас:
func getAngle() -> Float {
guard let pointOfView = self.sceneView.session.currentFrame else { return 0.0 }
let cameraPosition = pointOfView.camera.transform.columns.3
let heading = getUserVector()
let distance = SCNVector3Make(TargetPosition.x - cameraPosition.x ,TargetPosition.y - cameraPosition.y - TargetPosition.y,TargetPosition.z - cameraPosition.z)
let heading_scalar = sqrtf(heading.x * heading.x + heading.z * heading.z)
let distance_scalar = sqrtf(distance.z * distance.z + distance.z * distance.z)
let x = ((heading.x * distance.x) + (heading.z * distance.z) / (heading_scalar * distance_scalar))
let theta = acos(max(min(x, 1), -1))
if theta < 0.35 {
return 0
}
if (heading.x * (distance.z / distance_scalar) - heading.z * (distance.x/distance_scalar)) > 0{
return theta
}
else{
return -theta
}
}
func getUserVector() -> (SCNVector3) { // (direction)
if let frame = self.sceneView.session.currentFrame {
let mat = SCNMatrix4(frame.camera.transform) // 4x4 transform matrix describing camera in world space
let dir = SCNVector3(-1 * mat.m31, -1 * mat.m32, -1 * mat.m33) // orientation of camera in world space
print(mat)
return dir
}
return SCNVector3(0, 0, -1)
}
Рассмотрим следующее изображение в качестве примера.Стрелка в верхнем правом углу должна указывать прямо вверх, чтобы следовать линии к центру объекта, но вместо этого она указывает немного налево.Поскольку я выровнен по оси Z, то же поведение происходит при выравнивании по оси X.