SCNNode 面向摄像头

SCNNode facing towards the camera

我正在尝试将 SCNCylinder 节点放在场景中的触摸点上。我总是想展示面向相机的圆柱形直径。它在水平场景中工作正常,但在垂直场景中有问题。在垂直场景中,我可以看到圆柱体的侧面,但无论相机方向如何,我都想显示面向相机的完整直径。我知道需要根据相机变换应用一些变换,但不知道如何应用。我没有使用平面检测,它是直接添加到场景中的简单节点。

垂直图像:

水平图像:

插入节点的代码如下,

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
               guard let touch = touches.first else {
                    return
                }
                let result = sceneView.hitTest(touch.location(in: sceneView), types: [ARHitTestResult.ResultType.featurePoint])
                guard let hitResult = result.last else {
                    print("returning because couldn't find the touch point")
                    return
                }
                let hitTransform = SCNMatrix4(hitResult.worldTransform)
                let position = SCNVector3Make(hitTransform.m41, hitTransform.m42, hitTransform.m43)
                let ballShape = SCNCylinder(radius: 0.02, height: 0.01)

                let ballNode = SCNNode(geometry: ballShape)
                ballNode.position = position
                sceneView.scene.rootNode.addChildNode(ballNode)
}

如有任何帮助,我们将不胜感激。

我不确定这是处理您需要的正确方法,但这里有一些可能对您有所帮助。

我认为 CoreMotion 可以帮助您确定设备是处于水平角度还是垂直角度。

This class has a property called attitude, which describes the rotation of our device in terms of roll, pitch, and yaw. If we are holding our phone in portrait orientation, the roll describes the angle of rotation about the axis that runs through the top and bottom of the phone. The pitch describes the angle of rotation about the axis that runs through the sides of your phone (where the volume buttons are). And finally, the yaw describes the angle of rotation about the axis that runs through the front and back of your phone. With these three values, we can determine how the user is holding their phone in reference to what would be level ground (Stephan Baker).

首先导入 CoreMotion:

import CoreMotion

然后创建以下变量:

 let deviceMotionDetector = CMMotionManager()
 var currentAngle: Double!

然后我们将创建一个函数来检查我们设备的角度,如下所示:

   /// Detects The Angle Of The Device
func detectDeviceAngle(){

    if deviceMotionDetector.isDeviceMotionAvailable == true {

        deviceMotionDetector.deviceMotionUpdateInterval = 0.1;

        let queue = OperationQueue()

        deviceMotionDetector.startDeviceMotionUpdates(to: queue, withHandler: { (motion, error) -> Void in

            if let attitude = motion?.attitude {

                DispatchQueue.main.async {

                    let pitch = attitude.pitch * 180.0/Double.pi
                    self.currentAngle = pitch
                    print(pitch)

                }
            }

        })

    }
    else {
        print("Device Motion Unavailable");
    }

}

例如在viewDidLoad中只需要调用一次:

 detectDeviceAngle()

在您的 touchesBegan 方法中,您可以将其添加到末尾:

//1. If We Are Holding The Device Above 60 Degress Change The Node
if currentAngle > 60 {

    //2a. Get The X, Y, Z Values Of The Desired Rotation
    let rotation = SCNVector3(1, 0, 0)
    let vector3x = rotation.x
    let vector3y = rotation.y
    let vector3z = rotation.z
    let degreesToRotate:Float = 90

    //2b. Set The Position & Rotation Of The Object
    sphereNode.rotation = SCNVector4Make(vector3x, vector3y, vector3z, degreesToRotate * 180 / .pi)

}else{

}

我相信有更好的方法可以满足您的需求(我也很想听听它们),但我希望它能帮助您入门。

结果如下: