节点组的位置在SCNNode.runAction的开头重置 [英] Node group's position is reset at the start of SCNNode.runAction

查看:271
本文介绍了节点组的位置在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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆