SceneKit:围绕自身旋转节点

SceneKit: rotate node around itself

我想围绕它的 x 轴旋转一个节点(更具体地说,我想转动一个轮子)。

车轮是汽车的子节点。我在 Whosebug 上发现了几个关于这个问题的线程,例如 但没有一个解决方案对我有用:

我尝试了以下代码:

    if let wheel = sceneView.scene.rootNode.childNode(withName: "WheelRearL", recursively: true) {

        // also tried:
        // wheel.pivot = SCNMatrix4MakeTranslation(0.5, 0.5, 0.5)

        let (minVec, maxVec) = (wheel.boundingBox)
        wheel.pivot = SCNMatrix4MakeTranslation(-25, (maxVec.y - minVec.y) / 2 + minVec.y, (maxVec.z - minVec.z) / 2 + minVec.z)

    }

但是车轮还是绕着整车的中心转

以下代码用于旋转本身,但与我认为的解决方案无关:

        let spin = CABasicAnimation.init(keyPath: "rotation")
        spin.fromValue = NSValue(scnVector4: SCNVector4(x: 25, y: 0, z: 0, w: 0))
        spin.toValue = NSValue(scnVector4: SCNVector4(x:25, y: 0, z: 0, w: Float(CGFloat(2 * M_PI))))
        spin.duration = 3
        spin.repeatCount = .infinity
        let wheel = sceneView.scene.rootNode.childNode(withName: "WheelRearL", recursively: true)
        wheel?.addAnimation(spin, forKey: "spin around")

(顺便说一句:我需要更改代码中的枢轴,而无需在 SceneKit 界面构建器中设置额外的容器节点并将其移动到节点中心)

好吧,不知何故我找到了一个可行的解决方案:(不知道这是否是最好的方法 - 但它绝对适合我。)

    if let w = sceneView.scene.rootNode.childNode(withName: name, recursively: true) {
        let (minVec, maxVec) = w.boundingBox
        w.position.x = -25 / 100
        w.position.y = ((maxVec.y - minVec.y) / 2 + minVec.y) / 100
        w.position.z = ((maxVec.z - minVec.z) / 2 + minVec.z) / 100
        w.pivot = SCNMatrix4MakeTranslation(-25, (maxVec.y - minVec.y) / 2 + minVec.y, (maxVec.z - minVec.z) / 2 + minVec.z)
    }

节点的局部轴通常不像这颗心那样位于几何体的中心。

您有两个选项可以使轴重新居中。您可以在代码中添加一个函数。

 func centerPivot(for node: SCNNode) {
    var min = SCNVector3Zero
    var max = SCNVector3Zero
    node.__getBoundingBoxMin(&min, max: &max)
    node.pivot = SCNMatrix4MakeTranslation(
        min.x + (max.x - min.x)/2,
        min.y + (max.y - min.y)/2,
        min.z + (max.z - min.z)/2
    )
}

调用函数

centrePivot(for: wheelNode)

你像这样应用到节点。这会将枢轴放置在节点边界框​​的中心。但我发现你有时需要根据你需要从哪里开始修改那个函数......这可能是一个反复试验的过程,直到它的位置完美。

另一种方法是在 SketchUp 等 3D 创作工具中打开 collada(dae 文件),并在这种情况下(每个车轮几何形状)制作成一个组件(如果还没有的话) .从那里您可以重置组件轴,并将轴重新定位到每个车轮的几何中心。

在许多情况下,您想要制作动画的汽车、直升机和其他模型等的免费 dae 模型并不是作者为制作动画而创建的,因此动画几何的几何分组和轴不是在正确的枢轴位置。您可能还希望轴位于摆动门等的铰链上,这样它就会偏离中心,并且可以 fiddle 得到正确的结果。所以我认为最好知道如何在 3D 模型本身中进行轴调整(对于枢轴点)。

我知道现在回答已经很晚了。但我找到了一种绕自身轴旋转节点的方法。关键点是:创建父节点并将目标节点添加为子节点。 您可以使用下面的代码围绕其 X 轴旋转“hudNode”:

 let containerNode = SCNNode()
 containerNode.addChildNode(hudNode)  
 let roteAction = SCNAction.rotate(by: 3.14, around: SCNVector3(1,0,0), duration: 0)
        hudNode.runAction(roteAction)

然后你可以把containerNode放到你喜欢的任何地方。