当我的相机在z轴上时,我期待从上方看到金字塔.我设法旋转金字塔以这种方式看到,但是当我添加动画似乎在多轴上旋转时.
这是我的代码:
// The following create the pyramid and place it how I want let pyramid = SCNPyramid(width: 1.0,height: 1.0,length: 1.0) let pyramidNode = SCNNode(geometry: pyramid) pyramidNode.position = SCNVector3(x: 0,y: 0,z: 0) pyramidNode.rotation = SCNVector4(x: 1,z: 0,w: Float(M_PI / 2)) scene.rootNode.addChildNode(pyramidNode) // But the animation seems to rotate aroun 2 axis and not just z var spin = CABasicAnimation(keyPath: "rotation") spin.byValue = NSValue(SCNVector4: SCNVector4(x: 0,z: 1,w: 2*Float(M_PI))) spin.duration = 3 spin.repeatCount = HUGE pyramidNode.addAnimation(spin,forKey: "spin around")
相反,从动画(它绕着它指向的轴旋转)分离金字塔的固定方向(其顶点在-z方向).有两个好办法:
使金字塔节点获得一次旋转的另一个节点的子节点(绕x轴的π/ 2),并将旋转动画直接应用于pyramidNode. (在这种情况下,金字塔的顶点仍然指向其局部空间的y方向,因此您需要旋转该轴而不是z轴.)
>使用pivot属性来转换pyramidNode的内容的本地空间,并相对于其包含的空间生成pyramidNode.
let pyramid = SCNPyramid(width: 1.0,length: 1.0) let pyramidNode = SCNNode(geometry: pyramid) pyramidNode.position = SCNVector3(x: 0,z: 0) // Point the pyramid in the -z direction pyramidNode.pivot = SCNMatrix4MakeRotation(CGFloat(M_PI_2),1,0) scene.rootNode.addChildNode(pyramidNode) let spin = CABasicAnimation(keyPath: "rotation") // Use from-to to explicitly make a full rotation around z spin.fromValue = NSValue(SCNVector4: SCNVector4(x: 0,w: 0)) spin.toValue = NSValue(SCNVector4: SCNVector4(x: 0,w: CGFloat(2 * M_PI))) spin.duration = 3 spin.repeatCount = .infinity pyramidNode.addAnimation(spin,forKey: "spin around")
一些不相关的更改提高代码质量:
>需要进行显式转换以初始化SCNVector组件时使用CGFloat;使用Float或Double专门将会破坏32或64位架构.
>使用.infinity代替传统的BSD数学常量HUGE.这种类型推断了任何类型的spin.repeatCount,并使用为所有浮点类型定义的常量值.
>使用M_PI_2作为π/ 2来精确度.
>为动画使用let而不是var,因为我们从不分配一个不同的值来旋转.
关于CGFloat错误业务的更多信息:在Swift中,数字文字没有类型,直到它们需要一个表达式.这就是为什么你可以做的事情,如spin.duration = 3 – 即使持续时间是一个浮点值,Swift允许你传递一个“整数文字”.但是如果你让d = 3; spin.duration = d你会收到一个错误.为什么?因为变量/常量有明确的类型,Swift不会进行隐式类型转换. 3是无类型的,但是当它分配给d时,类型推断默认为选择Int,因为您没有指定任何其他内容.
如果您看到类型转换错误,您可能有代码混合从函数返回的文字,常量和/或值.您可以通过将表达式中的所有内容转换为CGFloat(或者您将传递该表达式的所有类型)转换为错误,从而使错误消失.当然,这将使您的代码无法读取和丑陋,所以一旦你开始工作,你可能会一次删除一个转换,直到找到一个这样的工作.