0

我的目标是在另一个包含 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但总是在相机视图中而不是在平面中间生成球体。

我在这里附上了一张图片,向您展示我所说的“中间”是什么意思。

在此处输入图像描述

请让我知道如何解决这个问题。

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

最好的。

4

1 回答 1

2

如果没有真正看到你的模型,或者你是如何添加 Sphere 的,我会冒险猜测,要么你没有将你的模型添加到正确的SCNNode,要么pivot你的模型没有居中。

如果你想用平面几何在你的 SCNNode 上放置一些东西,你可以将它的位置设置为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)

}

因此,示例用法可能如下所示:

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

}

您也可以在 rendererDidAddNode 委托回调结束时调用它,例如:

这两种方法都会导致如下结果:

在此处输入图像描述

更新:

由于您现在已经更改了问题,因此您可以尝试以下操作:

/// Loads An SCNSphere At The Position Of An ARAnchor
///
/// - Parameter plane: SCNNode
func loadSphereAtAnchorPosition(_ anchor: ARPlaneAnchor) {

    let sphereNode = SCNNode()
    let sphereNodeGeometry = SCNSphere(radius: 0.01)
    sphereNodeGeometry.firstMaterial?.diffuse.contents = UIColor.cyan
    sphereNode.geometry = sphereNodeGeometry

    sphereNode.position = SCNVector3(anchor.transform.columns.3.x,
                                     anchor.transform.columns.3.y,
                                     anchor.transform.columns.3.z)

    augmentedRealityView?.scene.rootNode.addChildNode(sphereNode)

}

希望能帮助到你...

于 2018-05-15T02:50:10.443 回答