在SceneKit iOS中使用平移手势旋转节点

我使用以下代码使用平移手势旋转节点。 我喜欢只在y轴上旋转我的节点。

let translation = gestureRecognize.translation(in: gestureRecognize.view!) let x = Float(translation.x) let y = Float(-translation.y) let anglePan = (sqrt(pow(x,2)+pow(y,2)))*(Float)(Double.pi)/180.0 var rotationVector = SCNVector4() rotationVector.x = 0.0 rotationVector.y = x rotationVector.z = 0.0 rotationVector.w = anglePan node.rotation = rotationVector if(gestureRecognize.state == UIGestureRecognizerState.ended) { let currentPivot = node.pivot let changePivot = SCNMatrix4Invert( node.transform) node.pivot = SCNMatrix4Mult(changePivot, currentPivot) node.transform = SCNMatrix4Identity } 

这适用于Euler设置为(x:0,y:0,z:0)的节点。 但是我的节点有Euler(x:-90,y:0,z:0)。 对于我上面的Euler值,代码以错误的角度旋转对象。 如何使用我/不同的Euler值旋转节点?

我想你可能会在这里做的事情过于复杂。

在我的例子中,我创建了一个带有SCNBox Geometry的SCNNode ,并根据你的例子设置它的Euler Angles :(x:-90,y:0,z:0)。

您需要做的第一件事是创建一个变量来存储围绕YAxis的rotationAngle:

 var currentAngleY: Float = 0.0 

然后尝试这个函数,以便围绕YAxis旋转你的节点(顺便说一下,它工作正常):

  /// Rotates An Object On It's YAxis /// /// - Parameter gesture: UIPanGestureRecognizer @objc func rotateObject(_ gesture: UIPanGestureRecognizer) { guard let nodeToRotate = currentNode else { return } let translation = gesture.translation(in: gesture.view!) var newAngleY = (Float)(translation.x)*(Float)(Double.pi)/180.0 newAngleY += currentAngleY nodeToRotate.eulerAngles.y = newAngleY if(gesture.state == .ended) { currentAngleY = newAngleY } print(nodeToRotate.eulerAngles) } 

希望能帮助到你…

旋转矢量应如下所示;

 rotation = SCNVector4(x: 0, y: 1, z: 0, w: some_angle_in_radians) 

x,y,z是归一化的单位向量w,以弧度表示

检查你的数学

 let anglePan = (sqrt(pow(x,2)+pow(y,2)))*(Float)(Double.pi)/180.0 

可能检查x,y的值应该是这样的

 let anglePan = (sqrt(pow(x*deg2rd,2)+pow(y*deg2rad,2))) 

这是如何做你想要的,这恰好是唯一的方法:

 BOOL shouldRotateCube; - (IBAction)handlePanGesture:(UIPanGestureRecognizer *)sender { if (sender.state == UIGestureRecognizerStateBegan) { shouldRotateCube = TRUE; } else if (sender.state == UIGestureRecognizerStateChanged && shouldRotateCube && fabs([sender translationInView:sender.view].y) > 10.0) { shouldRotateCube = FALSE; [SCNTransaction begin]; [SCNTransaction setCompletionBlock:^{ [SCNTransaction begin]; [SCNTransaction setAnimationDuration:0.15]; SCNVector3 nodeAngles = [node eulerAngles]; [node setEulerAngles:SCNVector3Make(nodeAngles.x + (([sender translationInView:sender.view].y > 0.0) ? degreesToRadians(90) : degreesToRadians(-90)), nodes[i].rotation.y, nodes[i].rotation.z)]; } [SCNTransaction commit]; }]; [SCNTransaction commit]; } } 

以下是它的工作原理: BOOL用于防止在设备屏幕上上下滑动手指而产生的多种平移手势调用,因为此特定代码一次将立方体旋转90°。 当您开始新手势时,它将允许您再次运行与旋转相关的代码。

translationInView方法使用两次:一次确保您想要在旋转立方体之前在任一方向上要求至少10的距离来旋转立方体,并且第二次确定是向上还是向下滑动(通过评估是否翻译价值是正面还是负面)。

由于我的立方体只是上下旋转,我在eulerAngles矢量的(x)值上加/减90°; 我将剩余的eulerAngles值放在各自的位置。

所有内容都放置在SCNTransaction内部,以设置旋转动画,并控制旋转动画的持续时间。

我确实尝试过其他所有类型的旋转方法,甚至是Core Animation等中的旋转方法 – 这就是所有这些都可以让你来回旋转立方体等,而不会发生奇怪的事情。 我有一个使用这个代码的应用程序,它工作正常。 如果您无法将其集成到自己的应用程序中,我很乐意随时将我的应用程序的代码转发给您。