首页 文章

SCNNode 面向相机

提问于
浏览
2

我试图将 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)
}

任何帮助,将不胜感激。

1 回答

  • 0

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

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

    在此输入图像描述

    这个类有一个名为 attitude 的属性,它描述了我们的设备在滚动,俯仰和偏航方面的旋转。如果我们以纵向方向握住手机,则滚动会描述围绕穿过手机顶部和底部的轴的旋转角度。音高描述了围绕穿过手机两侧的轴的旋转角度(音量按钮所在的位置)。最后,偏航描述围绕穿过手机正面和背面的轴的旋转角度。通过这三个值,我们可以确定用户如何拿着手机参考水平地面(斯蒂芬贝克)。

    首先导入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{
    
    }
    

    我相信有更好的方法来实现你所需要的(我也非常有兴趣听到它们),但我希望它会让你开始。

    结果如下:

    在此输入图像描述

相关问题