2

如何返回用于设置 SCNNode 的球体几何 (SCNSphere) 的半径。我想在相对于父节点移动一些子节点的方法中使用半径。下面的代码失败,因为结果节点似乎不知道半径,我不应该将节点传递给方法吗?

我的数组索引也没有说 Int 不是 Range。

我正在尝试从中构建一些东西

import UIKit
import SceneKit

class PrimitivesScene: SCNScene {

    override init() {
        super.init()
        self.addSpheres();
    }

    func addSpheres() {
        let sphereGeometry = SCNSphere(radius: 1.0)
        sphereGeometry.firstMaterial?.diffuse.contents = UIColor.redColor()
        let sphereNode = SCNNode(geometry: sphereGeometry)
        self.rootNode.addChildNode(sphereNode)

        let secondSphereGeometry = SCNSphere(radius: 0.5)
        secondSphereGeometry.firstMaterial?.diffuse.contents = UIColor.greenColor()
        let secondSphereNode = SCNNode(geometry: secondSphereGeometry)
        secondSphereNode.position = SCNVector3(x: 0, y: 1.25, z: 0.0)

        self.rootNode.addChildNode(secondSphereNode)
        self.attachChildrenWithAngle(sphereNode, children:[secondSphereNode, sphereNode], angle:20)
    }

    func attachChildrenWithAngle(parent: SCNNode, children:[SCNNode], angle:Int) {
        let parentRadius = parent.geometry.radius //This fails cause geometry does not know radius.

        for var index = 0; index < 3; ++index{
            children[index].position=SCNVector3(x:Float(index),y:parentRadius+children[index].radius/2, z:0);// fails saying int is not convertible to range.
        }


    }

    required init(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

}
4

2 回答 2

5

问题radius在于parent.geometry返回 aSCNGeometry而不是SCNSphere. 如果您需要获取radius,则需要先转换parent.geometrySCNSphere。为了安全起见,最好使用一些可选的绑定和链接来做到这一点:

if let parentRadius = (parent.geometry as? SCNSphere)?.radius {
    // use parentRadius here
}

访问节点radius上的时,您还需要这样做。children如果你把所有这些放在一起并稍微清理一下,你会得到这样的结果:

func attachChildrenWithAngle(parent: SCNNode, children:[SCNNode], angle:Int) {
    if let parentRadius = (parent.geometry as? SCNSphere)?.radius {
        for var index = 0; index < 3; ++index{
            let child = children[index]
            if let childRadius = (child.geometry as? SCNSphere)?.radius {
                let radius = parentRadius + childRadius / 2.0
                child.position = SCNVector3(x:CGFloat(index), y:radius, z:0.0);
            }
        }
    }
}

请注意,尽管您正在调用attachChildrenWithAngle一个包含 2 个孩子的数组:

self.attachChildrenWithAngle(sphereNode, children:[secondSphereNode, sphereNode], angle:20)

如果这样做,for当访问第三个元素时,您将在该循环中遇到运行时崩溃。每次调用该函数时,您要么需要传递一个包含 3 个子项的数组,要么更改该for循环中的逻辑。

于 2014-11-11T22:21:45.523 回答
0

此时我只使用球体,因此半径很容易操作。但是,我认为您应该尝试查看SCNNode 的几何形状。除了您发布的代码片段外,我还使用此功能(这两个对我来说很好)。

func updateRadiusOfNode(_ node: SCNNode, to radius: CGFloat) {
    if let sphere = (node.geometry as? SCNSphere) {
        if (sphere.radius != radius) {
            sphere.radius = radius
        }
    }
}

比例因子(在半径处)也很重要。我使用 baseRadius 然后我将它与

maxDistanceObserved / 2

如果 hitTest 有进一步的结果,总是更新最大距离。

于 2021-02-02T13:29:15.993 回答