旋转SceneKit中的节点

5

我很难理解节点的多次旋转。

首先,我创建并定位了一个平面:

SCNPlane *plane = [SCNPlane planeWithWidth:10 height:10];
SCNNode *planeNode = [SCNNode nodeWithGeometry:plane];
planeNode.rotation = SCNVector4Make(1, 0, 0, (M_PI/2 * 3));
[scene.rootNode addChildNode:planeNode];

然后我在这个平面上定位和设置了一个聚光灯节点的方向:
SCNLight *light = [[SCNLight alloc] init];
light.type = SCNLightTypeSpot;
light.spotInnerAngle = 70;
light.spotOuterAngle = 100;
light.castsShadow = YES;
lightNode = [SCNNode node];
lightNode.light = light;
lightNode.position = SCNVector3Make(4, 0, 0.5);
lightNode.rotation = SCNVector4Make(0, 1, 0, M_PI/2);
[planeNode addChildNode:lightNode];

然后我对光节点进行旋转动画,以x轴为轴心顺时针旋转90度:

[SCNTransaction begin];
[SCNTransaction setAnimationDuration:2.0];

lightNode.rotation = SCNVector4Make(1, 0, 0, M_PI/2);

[SCNTransaction commit];

但是我不明白为什么以下代码会使光节点绕着相同的轴旋转回原来的位置:
[SCNTransaction begin];
[SCNTransaction setAnimationDuration:2.0];

lightNode.rotation = SCNVector4Make(0, 1, 0, M_PI/2);

[SCNTransaction commit];

在我看来,这意味着我们正在沿着y轴将节点顺时针旋转90度。

有人能解释一下为什么这样可以实现吗?或者更好的方法是什么,可以将节点旋转然后返回到原始位置?

3个回答

15

我认为我已经通过使用欧拉角解决了这个问题,它似乎按照我理解的方式工作。

所以我替换了:

lightNode.rotation = SCNVector4Make(0, 1, 0, M_PI/2);

随着:

lightNode.eulerAngles = SCNVector3Make(0, M_PI/2, 0);

对于其他旋转方式同样适用。

我必须承认,我仍然非常困惑旋转方法的作用,但很高兴现在我有了可以使用的东西。


5
我不确定完全理解问题,但是当您编写lightNode.rotation = SCNVector4Make(0, 1, 0, M_PI/2);时,您并没有将旋转连接到节点的当前旋转。您正在指定一个新的“绝对”旋转。

由于SCNVector4Make(0, 1, 0, M_PI/2)lightNode的原始旋转,再次设置SCNVector4Make(0, 1, 0, M_PI/2)将使节点旋转回其原始状态。

编辑

以下代码执行两个操作

  1. first it sets an initial value for the node's rotation
  2. then it specifies a new value for the node's rotation. Because it is done in a transaction (whose duration is not 0) SceneKit will animate that change. But the parameters of the animation, including the rotation axis, are chosen by SceneKit.

    lightNode.rotation = SCNVector4Make(0, 1, 0, M_PI/2);
    
    [SCNTransaction begin];
    [SCNTransaction setAnimationDuration:2.0];
    lightNode.rotation = SCNVector4Make(1, 0, 0, M_PI/2);
    [SCNTransaction commit];
    

position属性也是一样的。下面这段代码将会使一个节点从(1,0,1)移动到(2,3,4),而不是从(1,1,1)移动到(3,3,5)

    aNode.position = SCNVector3Make(1, 0, 1);

    [SCNTransaction begin];
    [SCNTransaction setAnimationDuration:2.0];
    aNode.position = SCNVector3Make(2, 3, 4);
    [SCNTransaction commit];

如果你想对一个节点进行动画处理,并且希望能够控制动画参数,你可以使用一个带有byValueCABasicAnimation

谢谢回复,虽然我现在比以前更困惑了 :( 我完全不确定绝对旋转与我在这里尝试做的事情有什么区别(只是相对于平面旋转灯节点)。 我想我的问题基本上是:如何以相同的轴两次工作于同一位置并将节点旋转一次,然后回到其原始位置? 如果我所做的导致了绝对旋转(我猜这很糟糕),那么我应该使用另一种方法来实现我想要的效果吗? - bcl
再次感谢您的回复。不确定这是否符合我的要求,因为我不希望SceneKit选择动画的旋转轴;我需要在给定方向上进行非常特定的移动。在我看来,eulerAngles 给了我这种程度的控制,而且它不会通过切换我需要处理的旋转轴来使我困惑。 - bcl

0

因为当你搜索"scnnode旋转"时,它会首先显示出来。

node.localRotate(by: SCNQuaternion(x: 0, y: 0, z: -0.7071, w: 0.7071))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接