获取放置SCNNode的世界x,y和z - Swift

时间:2018-05-15 01:08:52

标签: swift arkit scnnode arscnview

我的目标是在包含SCNPlane的另一个SCNNode的中间生成一个SCNNode。

SCNPlane是在渲染器函数中生成的,如下所示:

func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
    guard let planeAnchor = anchor as? ARPlaneAnchor else { return }

    let width = CGFloat(planeAnchor.extent.x)
    let height = CGFloat(planeAnchor.extent.z)
    let plane = SCNPlane(width: width, height: height)

    plane.materials.first?.diffuse.contents = UIColor.orange

    let planeNode = SCNNode(geometry: plane)

    let x = CGFloat(planeAnchor.center.x)
    let y = CGFloat(planeAnchor.center.y)
    let z = CGFloat(planeAnchor.center.z)
    planeNode.position = SCNVector3(x,y,z)
    planeNode.eulerAngles.x = -.pi / 2

    node.addChildNode(planeNode)
    node.name = "plane"

    loadSphere(x:x, y:y, z:z)

我试图将球体正确地放在飞机中间:

func loadSphere (x:CGFloat, y:CGFloat, z:CGFloat) {
    let idleScene = SCNScene(named: "art.scnassets/bounceFixed.dae")!

    // This node will be parent of all the animation models
    let node = SCNNode()

    for child in idleScene.rootNode.childNodes {
        node.addChildNode(child)
    }

    // Set up some properties
    node.name = "Sphere"

    node.position = SCNVector3(x, y, z)
    node.scale = SCNVector3(0.001, 0.001, 0.001)
    ...

但问题是每当我运行它时,x,y,z都会变为零。我尝试了sceneView.scene.rootNode.childNodes[3].worldPositionnode.worldPosition之类的东西,但总是最终在相机视图中生成球体而不是在平面中间。

我在这里附上一张照片,告诉你我对“中间人”的意思。

enter image description here

请告诉我如何解决这个问题。

编辑:这篇文章的目标是尝试获取平面节点的x,y,z(中心)而不将球体作为子项附加。

最佳。

1 个答案:

答案 0 :(得分:2)

如果没有真正看到您的模型,或者您正在添加Sphere的确切方式,我会冒险猜测,您要么将模型添加到正确的SCNNode,要么{{1}你的模型没有居中。

如果您想在SCNNode上集中放置平面几何图形,可以将其设置在pivot或完全忽略它。

SCNVector3Zero

你可以在/// Loads An SCNSphere On A Generated SCNNode /// /// - Parameter plane: SCNNode func loadSphereOnPlane(_ plane: SCNNode) { let sphereNode = SCNNode() let sphereNodeGeometry = SCNSphere(radius: 0.01) sphereNodeGeometry.firstMaterial?.diffuse.contents = UIColor.cyan sphereNode.geometry = sphereNodeGeometry plane.addChildNode(sphereNode) } 委托回调的末尾称之为:

rendererDidAddNode

如果模型的枢轴不居中,您可以使用类似的东西来改变它:

loadSphereOnPlane(planeNode)

示例用法可能如此:

/// Changes The Pivot To The Center Of The Model
///
/// - Parameter model: SCNNode
func createCentralPivotFor(_ model: SCNNode){

    let (min, max) = model.boundingBox

    let dx = min.x + 0.5 * (max.x - min.x)
    let dy = min.y + 0.5 * (max.y - min.y)
    let dz = min.z + 0.5 * (max.z - min.z)
    model.pivot = SCNMatrix4MakeTranslation(dx, dy, dz)

}

您还可以在rendererDidAddNode委托回调的末尾调用,例如:

两种方法都会产生如下结果:

enter image description here

更新:

既然你现在已经改变了你的问题,你可以尝试这样的事情:

/// Loads Our Little Scatterbug
func loadScatterBugOnPlane(_ node: SCNNode) {

    let modelPath = "ARModels.scnassets/Scatterbug.scn"

    //1. Get The Reference To Our SCNScene & Get The Model Root Node
    guard let model = SCNScene(named: modelPath),
        let pokemonModel = model.rootNode.childNode(withName: "RootNode", recursively: false) else { return }

    let scatterBug = pokemonModel

    //2. Scale The Scatterbug
    scatterBug.scale = SCNVector3(0.002, 0.002, 0.002)

    //3. Set The Pivot
    createCentralPivotFor(scatterBug)

    //4. Add It To The Plane
    node.addChildNode(scatterBug)

}

希望它有所帮助...