首页 文章

找到用户在 ARKit 中面向的方向

提问于
浏览
2

我想知道我的相机在 ARKit 中面向的方向,以便我在我前面的物体上进行的操作是正确的(说向左滑动向左移动)。

现在我尝试使用 POV 方向(不起作用,因为它始终是正的)和节点方向(photo.worldFront.z - 这将起作用,除非应用旋转,一旦旋转超过 180 度,方向是错误的)。

有什么建议?

2 回答

  • 4

    你是对的,首先是pointOfView

    Hovewer 虽然rotationeulerAngles都描述了摄像机面向的方向,但在使用物体(例如在相机的空间放置或移动物体)时使用它们并不简单。

    相反,在世界空间中设置您的位置或运动矢量,然后使用相机的transform将其转换为相机的空间。

    在 Obj-C 中它会是这样的:

    simd_float4x4 transform = self.sceneView.pointOfView.simdTransform;
    simd_float4 myPosInWorldSpace = simd_make_float4(0.0, 0.0, -0.5, 1);
    simd_float4 myPosInCamSpace = simd_mul(transform, myPosInWorldSpace);
    

    将对象的位置设置为myPosInCamSpace。上面的示例将对象放在z=-0.5的相机空间中,该空间比 AR 中的相机高出半米。

    要将已经位于相机前方的物体向右移动 5 厘米,请执行以下操作:

    simd_float4x4 transform = self.sceneView.pointOfView.simdTransform;
    transform.columns[3].xyz=0; //drop cam translation
    simd_float4 myVecInWorldSpace = simd_make_float4(0.05, 0.0, 0.0, 1);
    simd_float4 myVecInCamSpace = simd_mul(transform, myVecInWorldSpace);
    

    myVecInCamSpace添加到您前面的对象的位置。

    第一修正案

    如果你需要完全 360°(-π,π)的摄像机偏航用于记录或其他:

    simd_float4x4 transform = self.sceneView.pointOfView.simdTransform;
    simd_float3 cam_right = transform.columns[0].xyz; //for completeness
    simd_float3 cam_up = transform.columns[1].xyz;  //for completeness
    simd_float3 cam_ahead = transform.columns[2].xyz;
    float yaw = atan2f(cam_ahead.x, cam_ahead.z);
    
  • 0

    我通过使用位置管理器磁性标题找到了一个更简单的解决方案。

    首先你需要这些功能

    func degreesToRadians(degrees: Double) -> Double { return degrees * .pi / 180.0 }
    func radiansToDegrees(radians: Double) -> Double { return radians * 180.0 / .pi }
    func getBearingBetweenTwoPoints1(point1 : CLLocation, point2 : CLLocation) -> Double {
    
        let lat1 = degreesToRadians(degrees: point1.coordinate.latitude)
        let lon1 = degreesToRadians(degrees: point1.coordinate.longitude)
    
        let lat2 = degreesToRadians(degrees: point2.coordinate.latitude)
        let lon2 = degreesToRadians(degrees: point2.coordinate.longitude)
    
        let dLon = lon2 - lon1
    
        let y = sin(dLon) * cos(lat2)
        let x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(dLon)
        let radiansBearing = atan2(y, x)
    
        return radiansToDegrees(radians: radiansBearing)
    }
    

    创建一个位置管理器。

    import CoreLocation
    

    class YourClass: CLLocationManagerDelegate {
    

    ..

    var locationManager:CLLocationManager = CLLocationManager()
    locationManager.delegate = self
    
    locationManager.startUpdatingHeading()
    var degreesRange:Int = 20
    

    在你每秒或更新会话(_:ARSession,didUpdate:ARFrame)或使用计时器或你写的任何内容更新的函数内部之后:

    “point2 将是你的位置”

    var degrees:Double = getBearingBetweenTwoPoints1(point1: locationManager.location!, point2: CLLocation(latitude: 70.500000, longitude: 85.555555))
    
    if(degrees < 0 ) {
        degrees = 360 + degrees
    }
    
    var locationManagerHeadingMagnetic:Double = lm.heading!.magneticHeading
    
    print("He Is Looking \(locationManagerHeadingMagnetic)")
    print("He should Look: \(degrees)")
    

    因此,如果您想查找他是否在寻找您的位置,您必须进行此检查。

    var difference:Double = locationManagerHeadingMagnetic - degrees
    print("Difference \(difference)")
    
    if(difference < degreesRange && difference > -degreesRange) {
        print("Correct Looking!")
    
    } else {
    
        if(difference <= -degreesRange || difference > 180) {
            print("You have to look more right!")
        } else {
            print("You have to look more left")
        }
    }
    

    在此示例中,如果用户从 20 度范围内的位置查看目的地,则会打印正确的查看!您可以根据需要自定义度数。

相关问题