【问题标题】:SCNNode facing towards the cameraSCNNode 朝向相机
【发布时间】:2018-08-24 03:12:42
【问题描述】:

我正在尝试将 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)
}

任何帮助将不胜感激。

【问题讨论】:

  • @Josh Robbins ,我注意到你回答了我的问题,我正在阅读它,然后它突然消失了。你把它拿走了。可以再发一次让我试试吗?
  • 我犯了一个错误,我不得不编辑 :)

标签: swift augmented-reality arkit scnnode scnscene


【解决方案1】:

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

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

这个类有一个叫做姿态的属性,它用滚动、俯仰和偏航来描述我们设备的旋转。如果我们以纵向方式握住手机,则滚动描述了围绕贯穿手机顶部和底部的轴的旋转角度。音高描述了围绕穿过手机侧面的轴(音量按钮所在的位置)的旋转角度。最后,偏航角描述了围绕贯穿手机正面和背面的轴的旋转角度。使用这三个值,我们可以确定用户如何参考水平地面 (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{

}

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

结果如下:

【讨论】:

  • 我刚刚测试了这个解决方案。它在纵向模式下工作正常,但在横向模式下不能旋转圆柱体。你有什么想法吗?
  • 您需要查看检测设备的方向,然后根据该方向调整代码:)
猜你喜欢
  • 1970-01-01
  • 2018-07-29
  • 1970-01-01
  • 2018-02-22
  • 2018-09-24
  • 2013-04-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多