当前位置: 首页 > 知识库问答 >
问题:

节点组的位置在SCNNode.run动作开始时重置

韦安怡
2023-03-14

我有一些代码,当点击屏幕时,会绕x轴旋转几个SCNNodes,如下所示:

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时将其从当前位置旋转?

在将节点添加到容器之前,我已经尝试从它们的原始父节点中删除它们,但是没有可见的效果。

我也尝试过使用动画

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

这和动作的效果完全一样。

如果我将节点作为根视图的子节点放回运行操作的完整块中

    container.runAction(action, completionHandler: { () -> Void in
        println("completed rotation")
        for node: SCNNode in slice {
            node.removeFromParentNode()
            sceneView.scene!.rootNode.addChildNode(node)
        }
    })

然后,节点会在动作完成时返回到其原始位置,而不是在新点击开始时。

共有2个答案

戴原
2023-03-14

这就是我如何在没有容器或类似东西的情况下旋转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)

重要的是将命令的使用shortestunitarc设置为truein。旋转到方法。这样,在旋转到所需角度之前,节点不必返回其原始角度。

葛雨华
2023-03-14

当节点从场景的根节点中移除、添加到容器并旋转时,将向相对于容器的局部坐标系的节点应用变换。解决方案是将节点的变换从容器的坐标系转换为根节点的坐标系,然后再将其添加回根节点。

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)
        }
    })
}
 类似资料:
  • 看看这支笔:https://codepen.io/segmentationfaulter/pen/XzgJyV 为了方便起见,我还在这里粘贴代码。打开上面的画笔后,您将看到一个滑块被渲染。向右滚动滑块,然后单击按钮,您将看到滑块以不同的数字重新渲染,但滑块的滚动位置不会重置。为什么滚动位置没有复位?谢谢

  • 问题内容: 在JavaFX中获取节点绝对位置的最佳方法是什么? 假设我们在窗格(Hbox,Stackpane或任何其他窗格)中有一个节点,并且它本身可能有一个父节点。 我想获取该节点的绝对位置,并在另一个窗格中使用它。 问题答案: 这取决于您所说的“绝对”的含义。节点有一个坐标系,父节点有一个坐标系,父节点有一个坐标系,依此类推,最终有一个坐标系和一个屏幕坐标系(可能是物理显示设备的集合)。 您可

  • 我实现了一个应用程序,将AR标签放置在特定的gps位置和ARCore位置(https://github.com/appoly/ARCore-Location).逻辑是基于gps位置和摄像头位置创建锚节点: ` ` 然后在anchorNode的Update()中,缩放并旋转呈现ar标签的节点: ` ` 代码设置了一个间隔(默认为5秒),在此间隔之后,会话将刷新锚点节点(分离旧锚点并创建新锚点)。 我

  • 因为要考虑canal启动后,从之前master的某个特定节点开始复制 目前msater是开启了gtid的 是在服务端配置、还是客户端配置? 是需要修改/example/instance.properties吗?

  • 问题内容: 说我有XML: 如何在As和C之间插入“ nodeB”?在PHP中,最好通过SimpleXML?喜欢: 问题答案: 以下是在其他一些SimpleXMLElement之后插入新的SimpleXMLElement的函数。由于使用SimpleXML不可能直接做到这一点,因此它在幕后使用了一些DOM类/方法来完成工作。 以及如何使用它的示例(特定于您的问题): 如果您想/需要解释它是 如何 工

  • 本文向大家介绍文本框倒叙输入让输入框的焦点始终在最开始的位置,包括了文本框倒叙输入让输入框的焦点始终在最开始的位置的使用技巧和注意事项,需要的朋友参考一下 所谓的文本框倒叙输入是指输入框的焦点始终在最开始的位置,如图所示,当我输入123456789时,在输入框上显示的是987654321。 为什么要做这个Demo?是因为在项目中遇到了,项目需求是两个输入框,一个正序输入,另一个倒叙输入。 下面我把