简体   繁体   English

节点组的位置在SCNNode.runAction的开头重置

[英]Node group's position is reset at the start of SCNNode.runAction

I have some code that rotates several SCNNodes around the x axis when the screen is tapped like so: 我有一些代码可以在屏幕被点击时围绕x轴旋转几个SCNNode:

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")
    })
}

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? 如何进行后续调用handleTap将它们从当前位置旋转?

I've tried removing the nodes from their original parent before adding them to the container, but it has no visible effect. 我尝试在将节点添加到容器之前从其原始父节点中删除节点,但它没有可见的效果。

I've also tried using an animation 我也试过用动画

    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. 其效果与动作完全相同。

If I put the nodes back as children of the root view in the complete block of the runAction 如果我将节点作为根视图的子节点放回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)
        }
    })
}

This is how I rotate a SCNNode without a container or anything like that: 这是我在没有容器或类似的东西的情况下旋转SCNNode

let targetRotationRadians: CGFloat = targetRotationAngle * (CGFloat.pi / 180.0)
let rotationAction = SCNAction.rotateTo(x: 0.0, y: targetRotationRadians, z: 0.0, duration: animationDuration, usesShortestUnitArc: true)
yourSCNNode.runAction(rotationAction)

The important thing is setting usesShortestUnitArc to true in for the SCNAction.rotateTo method. 重要的是为SCNAction.rotateTo方法设置usesShortestUnitArctrue That way, the node doesn't have to return to its original angle before rotating to the desired angle. 这样,节点在旋转到所需角度之前不必返回其原始角度。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM