Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 如何将三维对象(.scn文件)放置在检测到的垂直平面上,该垂直平面应与ARKIt中的平面平行?_Ios_Swift_3d_Arkit - Fatal编程技术网

Ios 如何将三维对象(.scn文件)放置在检测到的垂直平面上,该垂直平面应与ARKIt中的平面平行?

Ios 如何将三维对象(.scn文件)放置在检测到的垂直平面上,该垂直平面应与ARKIt中的平面平行?,ios,swift,3d,arkit,Ios,Swift,3d,Arkit,我将检测ARKit中的水平面和垂直面。检测到是水平面还是垂直面后,分别在检测到的表面上添加灰色平面。点击检测到的平面,我将添加.scn文件的3D对象 我的代码在水平面上放置3D对象(.scn文件)时运行良好,但在垂直面上运行不正常 在SceneKit编辑器中,垂直平面(如相框)的3D对象(.scn文件)面向右侧。所以我把它的EularAngleY改为-0,现在在SceneKit编辑器中它正对着前面。当我点击检测到的垂直面,它面向前方,然后相框也面向右侧,如果我向右移动设备并放置相框,则它是正确的

我将检测ARKit中的水平面和垂直面。检测到是水平面还是垂直面后,分别在检测到的表面上添加灰色平面。点击检测到的平面,我将添加.scn文件的3D对象

我的代码在水平面上放置3D对象(.scn文件)时运行良好,但在垂直面上运行不正常

在SceneKit编辑器中,垂直平面(如相框)的3D对象(.scn文件)面向右侧。所以我把它的EularAngleY改为-0,现在在SceneKit编辑器中它正对着前面。当我点击检测到的垂直面,它面向前方,然后相框也面向右侧,如果我向右移动设备并放置相框,则它是正确的

我想放置3D object.scn文件,该文件应平行于平面(如果垂直平面朝向前方,则即使在.scn文件中,该文件也应朝向前方,即使该文件朝向任何方向)。该3D对象与检测到的平面不平行

我是否还需要改变相对于检测到的平面角度的旋转,或者需要在SceneKit编辑器的.scn文件中进行任何更改?我怎样才能做到呢

请检查以下关于撞击检测到的垂直平面的代码。有什么问题吗

@objc func addObjectToSceneView1(withGestureRecognizer recognizer: UIGestureRecognizer){
    let tapLocation = recognizer.location(in: sceneView)
    let hitTestResults = sceneView.hitTest(tapLocation, types: .existingPlaneUsingExtent)

    guard let hitTestResult = hitTestResults.first, let anchor = hitTestResult.anchor as? ARPlaneAnchor else { return }


    let translation = hitTestResult.worldTransform.columns.3

    let x = translation.x
    let y = translation.y
    let z = translation.z

    guard let shipScene = SCNScene(named: "art.scnassets/frame/frame.scn"),
        let shipNode = shipScene.rootNode.childNode(withName: "frame", recursively: true)
        else { return }

    shipNode.position = SCNVector3(x,y,z)

    sceneView.scene.rootNode.addChildNode(shipNode)
}
.scn文件如下所示。这个.scn文件正确吗?或者x应该和框架的深度一致?每次我在飞机上点击时,它只会显示这样的图像


正如我在回答中提到的,最好在
ARSession
中添加
ARAnchor
,而不是在执行命中测试后直接在场景图中添加
SCNNode
。当前,您发布的代码未考虑检测到的平面的旋转。为了使代码正常工作,您需要确定检测到的平面的法线,将点积和叉积与模型的所需方向计算旋转,然后应用旋转。但是,
ARSession
将为您完成所有这些。通过使用
ARAnchor(transform:hitTestResult.worldTransform)
将旋转编码到锚定中。因此,您只需要使用模型自己的局部坐标空间处理变换

例如:

@objc func addObjectToSceneView1(withGestureRecognizer recognizer: UIGestureRecognizer){
    let tapLocation = recognizer.location(in: sceneView)
    let hitTestResults = sceneView.hitTest(tapLocation, types: .existingPlaneUsingExtent)

    guard let hitTestResult = hitTestResults.first, let anchor = hitTestResult.anchor as? ARPlaneAnchor else { return }
    // create anchor and add to session and wait for callback
    let anchor = ARAnchor(transform: hitTestResult.worldTransform)
    sceneView.session.add(anchor: anchor)
}
然后,在您的会话中,代表回拨:

func renderer(_ renderer: SCNSceneRenderer, nodeFor anchor: ARAnchor) -> SCNNode? {
    if anchor is ARPlaneAnchor {
        // node for plane anchor
        let anchorNode = SCNNode()
        return anchorNode
    } else {
        // must be node for most recent hit test
        guard let frameScene = SCNScene(named: "art.scnassets/frame/frame.scn"),
              let frameNode = frameScene.rootNode.childNode(withName: "frame", recursively: true) else { return nil }
        return frameNode
    }
}
在您的scn文件中,您将希望模型位于原点,无需任何变换。这意味着您可能需要嵌套节点,并相对于父空节点定位基础模型

这里,“frame”是从
nodeforchanator
返回的没有变换的外部节点,“picture”旋转为平面并缩放到内容的大小

最终结果:


正如我在回答中提到的,最好在
ARSession
中添加
ARAnchor
,而不是在执行命中测试后直接在场景图中添加
SCNNode
。当前,您发布的代码未考虑检测到的平面的旋转。为了使代码正常工作,您需要确定检测到的平面的法线,将点积和叉积与模型的所需方向计算旋转,然后应用旋转。但是,
ARSession
将为您完成所有这些。通过使用
ARAnchor(transform:hitTestResult.worldTransform)
将旋转编码到锚定中。因此,您只需要使用模型自己的局部坐标空间处理变换

例如:

@objc func addObjectToSceneView1(withGestureRecognizer recognizer: UIGestureRecognizer){
    let tapLocation = recognizer.location(in: sceneView)
    let hitTestResults = sceneView.hitTest(tapLocation, types: .existingPlaneUsingExtent)

    guard let hitTestResult = hitTestResults.first, let anchor = hitTestResult.anchor as? ARPlaneAnchor else { return }
    // create anchor and add to session and wait for callback
    let anchor = ARAnchor(transform: hitTestResult.worldTransform)
    sceneView.session.add(anchor: anchor)
}
然后,在您的会话中,代表回拨:

func renderer(_ renderer: SCNSceneRenderer, nodeFor anchor: ARAnchor) -> SCNNode? {
    if anchor is ARPlaneAnchor {
        // node for plane anchor
        let anchorNode = SCNNode()
        return anchorNode
    } else {
        // must be node for most recent hit test
        guard let frameScene = SCNScene(named: "art.scnassets/frame/frame.scn"),
              let frameNode = frameScene.rootNode.childNode(withName: "frame", recursively: true) else { return nil }
        return frameNode
    }
}
在您的scn文件中,您将希望模型位于原点,无需任何变换。这意味着您可能需要嵌套节点,并相对于父空节点定位基础模型

这里,“frame”是从
nodeforchanator
返回的没有变换的外部节点,“picture”旋转为平面并缩放到内容的大小

最终结果:


你好,贝奥武夫,我已经添加了.scn文件。你能检查一下,让我知道所有方向和轴线都可以吗。我的意思是x轴是宽度,z轴是深度。当我运行这个项目时,它显示的正是这样。你能分享这个GIF的完整项目吗@beyowulf你好,beyowulf,我已经添加了.scn文件。你能检查一下,让我知道所有方向和轴线都可以吗。我的意思是x轴是宽度,z轴是深度。当我运行这个项目时,它显示的正是这样。你能分享这个GIF的完整项目吗@贝奥武夫