SceneKit:围绕自己旋转节点

时间:2018-01-26 13:24:47

标签: ios swift 3d scenekit arkit

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

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

我尝试了以下代码:

    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界面构建器中设置其他容器节点并将其移动到节点中心)

3 个答案:

答案 0 :(得分:2)

节点的局部轴通常不在几何体的中心,就像这颗心的情况一样。

enter image description here

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

 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)

您应用于节点,如此。这会将枢轴放在节点边界框​​的中心。但我发现你有时需要修改这个功能,具体取决于你需要转向的地方......它可以是一个试错过程,直到它的位置完美。

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

在许多情况下,汽车,直升机和其他想要制作动画的模型等的自由dae模型并非由作者创建并打算设置动画,因此动画几何体的几何分组和轴不在正确的枢轴位置。您可能还希望轴在铰链上用于摆动门等,因此它将偏离中心并且可以摆弄以使其正确。所以我认为最好知道如何在3D模型本身中进行轴调整(对于枢轴点)。

答案 1 :(得分:0)

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

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

答案 2 :(得分:0)

我知道现在回答已经很晚了。但是我找到了一种方法来围绕自身的轴旋转节点。关键点是:创建一个父节点并将目标节点添加为子节点。 您可以使用以下代码围绕其 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放到你喜欢的任何地方。