我有这本书,但是我正在从AR / VR周免费的视频教程中重新混合家具应用程序。
我想让3D墙面画布与检测到的墙/垂直平面对齐。
事实证明这比我想的要难。定位不是问题。与家具放置应用程序非常相似,您只需获取hittest.worldtransform的column3并为该向量3提供新的几何体位置。
但是我不知道我该怎么做才能使3D对象旋转到在对齐的检测平面上面向前方。因为我有一个画布对象,所以照片在画布的一侧。在放置时,照片始终朝外。
我考虑过对画布进行任意旋转以使其面向前方,但是那只有在我向北看并将画布放在我右边的墙上时才是正确的。
我已经在线尝试了很多解决方案,但其中一个始终使用.existingPlaneUsingExtent。用于垂直平面检测。这使您可以从以下位置获取ARPlaneAnchor:
hittest.anchor? as ARPlaneAnchor
。
如果在使用.estimatedVerticalPlane
anchor
时尝试这样做?是nil
当我的水平3D对象开始悬空时,我也没有继续沿着这条路线走。这可能取决于控制流逻辑,但在垂直画布放置起作用之前,我一直忽略它。
我当前的思路是获取画布的前向矢量,并将其向着检测到的UIImage
或命中点的垂直平面的前向矢量旋转。
如何从3D点获得前向矢量。还是从网格图像中获得前向量,即UIImage
检测到垂直墙时将ARKit
放置为叠加层?
这里是一个例子。画布显示画布的背面,并且与检测到的垂直列(即列)不平行。但是有一个“将海报放置在此处”网格,这是我希望画布与之对齐并能够看到照片的地方。
我尝试过的事情。
使用.estimatedVerticalPlane
ARKit estimatedVerticalPlane hit test get plane rotation
我不知道如何正确应用该矩阵和SO答案中的欧拉角结果。
我添加图片功能。
func addPicture(hitTestResult: ARHitTestResult) {
// I would like to convert estimate hitTest to a anchorpoint
// it is easier to rotate a node to a anchorpoint over calculating eularAngles
// we have all detected anchors in the _Renderer SCNNode. however there are
// Get the current furniture item, correct its position if necessary,
// and add it to the scene.
let picture = pictureSettings.currentPicturePiece()
//look for the vertical node geometry in verticalAnchors
if let hitPlaneAnchor = hitTestResult.anchor as? ARPlaneAnchor {
if let anchoredNode = verticalAnchors[hitPlaneAnchor]{
//code removed as a .estimatedVerticalPlane hittestResult doesn't get here
}
}else{
// Transform hitresult to world coords
let worldTransform = hitTestResult.worldTransform
let anchoredNodeOrientation = worldTransform.eulerAngles
picture.rotation.y =
-.pi * anchoredNodeOrientation.y
//set the transform matirs
let positionMatris = worldTransform.columns.3
let position = SCNVector3 (
positionMatris.x,
positionMatris.y,
positionMatris.z
)
picture.position = position + pictureSettings.currentPictureOffset();
}
//parented to rootNode of the scene
sceneView.scene.rootNode.addChildNode(picture)
}
感谢任何可用的帮助。
编辑: 我注意到“手形”或3D模型不正确/相反? 正Z指向左侧,正X面向相机,因为我期望的是模型的正面。这是问题吗?
答案 0 :(得分:0)
您应该避免使用世界坐标将节点直接添加到场景中。相反,您应该通过添加ARSession
来通知ARAnchor
感兴趣的区域,然后使用会话回调为添加的锚点出售SCNNode
。
例如,您的点击测试可能类似于:
@objc func tapped(_ sender: UITapGestureRecognizer) {
let location = sender.location(in: sender.view)
guard let hitTestResult = sceneView.hitTest(location, types: [.existingPlaneUsingGeometry, .estimatedVerticalPlane]).first,
let planeAnchor = hitTestResult.anchor as? ARPlaneAnchor,
planeAnchor.alignment == .vertical else { return }
let anchor = ARAnchor(transform: hitTestResult.worldTransform)
sceneView.session.add(anchor: anchor)
}
此处识别出的轻击手势用于检测ARSCNView
中的轻击。当检测到轻击时,执行命中测试以查找现有平面和估计平面。如果飞机是垂直的,我们在命中测试结果的ARAnchor
上添加worldTransform
,并将锚点添加到ARSession
。这会将该点注册为ARSession
的关注区域,因此在其中添加内容后,我们将获得更好的跟踪和更少的漂移。
接下来,我们需要为新添加的SCNNode
出售ARAnchor
。例如
func renderer(_ renderer: SCNSceneRenderer, nodeFor anchor: ARAnchor) -> SCNNode? {
if anchor is ARPlaneAnchor {
let anchorNode = SCNNode()
anchorNode.name = "anchor"
return anchorNode
} else {
let plane = SCNPlane(width: 0.67, height: 1.0)
plane.firstMaterial?.diffuse.contents = UIImage(named: "monaLisa")
let planeNode = SCNNode(geometry: plane)
planeNode.eulerAngles = SCNVector3(CGFloat.pi * -0.5, 0.0, 0.0)
let node = SCNNode()
node.addChildNode(planeNode)
return node
}
}
在这里,我们首先检查锚点是否为ARPlaneAnchor
。如果是这样,我们将出售一个空节点用于调试。如果不是,则是命中测试结果中添加的锚。因此,我们为最近的拍子创建了几何图形和节点。因为它是一个垂直平面并且我们的内容平放,所以需要绕x轴旋转它。因此,我们将其调整为eulerAngles
以使其直立。如果我们要返回planeNode
,则将直接删除对eulerAngles
的调整,因此我们将其添加为空节点的子节点并返回。
应该导致类似以下的情况。