节点组的位置在SCNNode.runAction的开头重置 [英] Node group's position is reset at the start of SCNNode.runAction
问题描述
我有一些代码可以在点击屏幕时围绕x轴旋转几个SCNNode:
I have some code that rotates several SCNNodes around the x axis when the screen is tapped like so:
func handleTap(gestureRecognize: UIGestureRecognizer) {
let sceneView = self.view as SCNView
let slice = self.cubes[0...8]
let container = SCNNode()
for node: SCNNode in slice {
container.addChildNode(node)
}
sceneView.scene!.rootNode.addChildNode(container)
container.runAction(SCNAction.rotateByX(CGFloat(M_PI / 2), y: 0.0, z: 0.0, duration: 1), completionHandler: { () -> Void in
println("complete")
})
}
我遇到的问题是每次调用此函数时,节点似乎在执行动作之前将自己重置为原始位置。操作完成后,它们似乎保持在正确的位置,直到再次点击屏幕。如何进行后续调用 handleTap
将它们从当前位置旋转?
The issue that I'm running into is that every time this function is called, the nodes seem to reset themselves to their original position before performing the action. When the action is complete, they appear to stay in the correct place until the screen is tapped again. How do I make subsequent calls to handleTap
rotate them from their current position?
我尝试删除节点在将它们添加到容器之前从它们的原始父级开始,但它没有可见效果。
I've tried removing the nodes from their original parent before adding them to the container, but it has no visible effect.
我也尝试过使用动画
let spin = CABasicAnimation(keyPath: "rotation")
spin.fromValue = NSValue(SCNVector4: SCNVector4(x: -1, y: 0, z: 0, w: 0))
spin.toValue = NSValue(SCNVector4: SCNVector4(x: -1, y: 0, z: 0, w: Float(M_PI_2)))
spin.duration = 3
spin.repeatCount = .infinity
container.addAnimation(spin, forKey: "spin around")
与行动具有完全相同的效果。
Which had the exact same effect as the action.
如果我将节点作为根视图的子节点放回完整块中runAction
If I put the nodes back as children of the root view in the complete block of the runAction
container.runAction(action, completionHandler: { () -> Void in
println("completed rotation")
for node: SCNNode in slice {
node.removeFromParentNode()
sceneView.scene!.rootNode.addChildNode(node)
}
})
然后节点在完成操作时返回到原始位置,而不是在开始时新的点击。
Then the nodes are returned to their original position on completion of the action, rather than at the beginning of a new tap.
推荐答案
当从场景的根节点中删除节点,添加到容器并旋转时,将应用转换相对于容器的本地坐标系的节点。解决方案是将节点的变换从容器的坐标系转换为根节点的坐标系,然后再将其添加回根节点。
When the node is removed from the scene's root node, added to the container and rotated, a tranform is applied to the node relative to the container's local coordinate system. The solution was to convert the node's transform from the container's coordinate system to the root node's coordinate system before adding it back to the root node.
func handleTap(gestureRecognize: UIGestureRecognizer) {
let sceneView = self.view as SCNView
let action = SCNAction.rotateByAngle(CGFloat(M_PI_2), aroundAxis: SCNVector3Make(-1, 0, 0), duration: 1)
let slice = self.cubes[0...8]
let container = SCNNode()
let root = sceneView.scene!.rootNode
for node: SCNNode in slice {
container.addChildNode(node)
}
root.addChildNode(container)
container.runAction(action, completionHandler: { () -> Void in
for node: SCNNode in slice {
let transform = node.parentNode!.convertTransform(node.transform, toNode: root)
node.removeFromParentNode()
node.transform = transform
root.addChildNode(node)
}
})
}
这篇关于节点组的位置在SCNNode.runAction的开头重置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!