我使用以下代码使用平移手势旋转节点。我喜欢只在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值旋转节点?
答案 0 :(得分:4)
我认为你可能会过度复杂化你需要做的事情。
在我的示例中,我创建了SCNNode
SCNBox
Geometry,并根据您的示例设置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)
}
希望它有所帮助...
答案 1 :(得分:0)
旋转矢量应如下所示;
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)))
答案 2 :(得分:0)
以下是如何做你想做的事情,这恰好是唯一的方法:
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的距离,第二次确定是否在滑动向上或向下(通过评估翻译价值是正还是负)。
由于我的立方体只是上下旋转,我向{/ 1}}向量的(x)值加上或减去了90°;我将剩余的eulerAngles
值放在各自的位置。
所有内容都放置在SCNTransaction内部,以设置旋转动画,并控制旋转动画的持续时间。
我确实尝试过所有其他类型的旋转方法,即使是核心动画等等 - 这就是所有这些都可以让你来回旋转立方体等,而不会发生奇怪的事情。我有一个使用这个代码的应用程序,它工作正常。如果您在将其集成到自己的应用程序中时遇到问题,我很乐意随时将应用程序的代码转发给您。