Swift SCNNode朝向相机

Swift SCNNode朝向相机,swift,augmented-reality,arkit,scnnode,scnscene,Swift,Augmented Reality,Arkit,Scnnode,Scnscene,我试图将SCNCylinder节点放置在触摸点的场景中。我总是想显示圆柱形状的直径朝向相机。它在水平场景中工作良好,但在垂直场景中存在问题。在垂直场景中,我可以看到圆柱体的侧面,但我想显示朝向摄影机的整个直径,无论摄影机的方向是什么。我知道需要根据相机变换应用一些变换,但不知道如何应用。我没有将平面检测用于直接添加到场景中的简单节点 垂直图像: 水平图像: 插入节点的代码如下所示 override func touchesBegan(_ touches: Set<UITouch>

我试图将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)
}
override func touchsbegind(touch:Set,带有事件:UIEvent?){
保护让触摸=触摸。首先触摸{
返回
}
让结果=sceneView.hitTest(touch.location(在:sceneView中),类型:[ARHitTestResult.ResultType.featurePoint])
guard let hitResult=result.last else{
打印(“由于找不到接触点而返回”)
返回
}
让hitTransform=SCNMatrix4(hitResult.worldTransform)
让位置=SCTransformer3Make(hitTransform.m41、hitTransform.m42、hitTransform.m43)
让ballShape=SCN气缸(半径:0.02,高度:0.01)
设ballNode=SCNNode(几何图形:ballShape)
ballNode.position=位置
sceneView.scene.rootNode.addChildNode(ballNode)
}

任何帮助都将不胜感激。

我不确定这是处理您需要的东西的正确方法,但这里有一些东西可以帮助您

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

这个类有一个叫做姿态的属性,它描述了我们的设备在横摇、俯仰和偏航方面的旋转。如果我们以纵向方向握住手机,则滚动描述绕穿过手机顶部和底部的轴旋转的角度。音高表示绕穿过手机两侧(音量按钮所在位置)的轴旋转的角度。最后,偏航描述了绕穿过手机前后的轴旋转的角度。有了这三个值,我们就可以确定用户是如何根据水平地面()握住手机的

首先导入
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()
在ToucheSBegind方法中,您可以将以下内容添加到末尾:

//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{

}
我相信有更好的方法来实现你的需求(我也非常有兴趣听到他们),但我希望这能让你开始

结果如下:


@Josh Robbins,我注意到你回答了我的问题,我正在读,然后突然它不见了。你把它拿走了吗。你能不能再发一次,这样我就可以试试?我犯了一个错误,不得不编辑:)我刚刚测试了这个解决方案。在纵向模式下工作良好,但在横向模式下不旋转圆柱体。你有什么想法吗?你需要看看检测设备snd的方向,然后根据它调整代码:)