Ios 如何将三维对象(.scn文件)放置在检测到的垂直平面上,该垂直平面应与ARKIt中的平面平行?
我将检测ARKit中的水平面和垂直面。检测到是水平面还是垂直面后,分别在检测到的表面上添加灰色平面。点击检测到的平面,我将添加.scn文件的3D对象 我的代码在水平面上放置3D对象(.scn文件)时运行良好,但在垂直面上运行不正常 在SceneKit编辑器中,垂直平面(如相框)的3D对象(.scn文件)面向右侧。所以我把它的EularAngleY改为-0,现在在SceneKit编辑器中它正对着前面。当我点击检测到的垂直面,它面向前方,然后相框也面向右侧,如果我向右移动设备并放置相框,则它是正确的 我想放置3D object.scn文件,该文件应平行于平面(如果垂直平面朝向前方,则即使在.scn文件中,该文件也应朝向前方,即使该文件朝向任何方向)。该3D对象与检测到的平面不平行 我是否还需要改变相对于检测到的平面角度的旋转,或者需要在SceneKit编辑器的.scn文件中进行任何更改?我怎样才能做到呢 请检查以下关于撞击检测到的垂直平面的代码。有什么问题吗Ios 如何将三维对象(.scn文件)放置在检测到的垂直平面上,该垂直平面应与ARKIt中的平面平行?,ios,swift,3d,arkit,Ios,Swift,3d,Arkit,我将检测ARKit中的水平面和垂直面。检测到是水平面还是垂直面后,分别在检测到的表面上添加灰色平面。点击检测到的平面,我将添加.scn文件的3D对象 我的代码在水平面上放置3D对象(.scn文件)时运行良好,但在垂直面上运行不正常 在SceneKit编辑器中,垂直平面(如相框)的3D对象(.scn文件)面向右侧。所以我把它的EularAngleY改为-0,现在在SceneKit编辑器中它正对着前面。当我点击检测到的垂直面,它面向前方,然后相框也面向右侧,如果我向右移动设备并放置相框,则它是正确的
@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的完整项目吗@贝奥武夫