ios ARKit隐藏墙后对象

js4nwp54  于 2023-01-27  发布在  iOS
关注(0)|答案(5)|浏览(154)

如何使用ARKit追踪的水平和垂直平面将物体隐藏在墙后/真实的物体后?目前,当你离开房间时,3D添加的物体可以透过墙壁看到,或者在物体前面看到。那么,是否可以使用ARKit提供的数据来提供更自然的AR体验,而不需要透过墙壁看到物体?

t3psigkw

t3psigkw1#

你现在有两个问题。
(And你甚至没有use regular expressions!)

如何为ARKit/SceneKit创建闭塞几何结构?

如果将SceneKit材质的colorBufferWriteMask设置为空值(Swift中的[]),任何使用该材质的对象都不会出现在视图中,但它们在渲染过程中仍然会写入z缓冲区,这会影响其他对象的渲染。实际上,你会得到一个形状与对象相似的“洞”,背景通过它显示出来(在ARSCNView的情况下为摄影机提要),但仍会遮挡其他SceneKit对象。
你还需要确保一个被遮挡的节点在其他节点被遮挡之前渲染。你可以使用节点层次结构来做到这一点(我一时记不清父节点是在子节点之前呈现还是相反,但很容易测试)层次结构中的对等节点没有确定的顺序,但是您可以使用renderingOrder属性强制执行顺序,而不管层次结构如何。该属性默认为零,因此将其设置为-1将在所有内容之前呈现。(或者,为了进行更精细的控制,将多个节点的renderingOrder设置为一系列值。)

如何检测墙壁/等,以便您知道将遮挡几何体放在何处?

在iOS 11.3及更高版本中(又名“ARKit 1.5”),您可以打开vertical平面检测。(请注意,当你把vertical平面锚点从那里拿回来时,它们会自动旋转。因此,如果你把模型附加到锚点上,它们的局部“向上”方向与平面垂直。)iOS 11.3中的另一项新功能是,可以为每个检测到的平面获取更详细的形状估计(请参见ARSCNPlaneGeometry),而不管其方向如何。
然而,即使你有水平和垂直方向,一个平面的外部界限也只是随着时间的推移而变化的估计值。也就是说,ARKit可以快速检测到墙的一部分在哪里,但如果用户不花时间挥动设备来绘制空间,它就不知道墙的边缘在哪里。即使这样,绘制的边缘可能也不会与真实的的墙精确对齐。
所以...如果使用检测到的垂直平面遮挡虚拟几何体,您可能会发现本应隐藏的虚拟对象显示出来的地方,要么是没有完全隐藏在墙的边缘,要么是通过ARKit没有Map整个真实的墙的地方可见。(后一个问题可以通过假设比ARKit更大的范围来解决。

ztmd8pv5

ztmd8pv52#

要创建遮挡材质(也称为黑洞材质或阻挡材质),必须使用下列示例属性:x一个一个一个一个一个x、x一个一个一个一个一个x、x一个一个一个二个一个x和x一个一个一个三个一个x。
您可以按以下方式使用它们:

plane.geometry?.firstMaterial?.isDoubleSided = true
plane.geometry?.firstMaterial?.colorBufferWriteMask = .alpha  
plane.geometry?.firstMaterial?.writesToDepthBuffer = true
plane.geometry?.firstMaterial?.readsFromDepthBuffer = true
plane.renderingOrder = -100

......或者这样:

func occlusion() -> SCNMaterial {

    let occlusionMaterial = SCNMaterial()
    occlusionMaterial.isDoubleSided = true
    occlusionMaterial.colorBufferWriteMask = []
    occlusionMaterial.readsFromDepthBuffer = true
    occlusionMaterial.writesToDepthBuffer = true

    return occlusionMaterial
}

plane.geometry?.firstMaterial = occlusion()
plane.renderingOrder = -100
w41d8nur

w41d8nur3#

要创建遮挡材质非常简单

let boxGeometry = SCNBox(width: 0.1, height: 0.1, length: 0.1, chamferRadius: 0)

    // Define a occlusion material 
    let occlusionMaterial = SCNMaterial()
    occlusionMaterial.colorBufferWriteMask = []

    boxGeometry.materials = [occlusionMaterial]
    self.box = SCNNode(geometry: boxGeometry)
    // Set rendering order to present this box in front of the other models
    self.box.renderingOrder = -1
sc4hvdpw

sc4hvdpw4#

伟大的解决方案:
GitHub: arkit-occlusion
对我有用。
但是在我的例子中,我想通过代码设置墙,所以如果你不想通过用户设置墙-〉使用平面检测来检测墙并通过代码设置墙。
或者在4米范围内,iphone depht传感器可以工作,你可以用ARHitTest探测障碍物。

relj7zay

relj7zay5#

ARKit 6.0和激光雷达扫描仪

你可以隐藏任何物体背后的虚拟无形的墙,复制真实的墙壁几何形状。iPhone和iPad Pro配备了LiDAR扫描仪帮助我们重建周围环境的3d拓扑图LiDAR扫描仪大大提高了Z通道的质量,允许遮挡或删除AR场景中的人。
LiDAR还改进了诸如对象遮挡之类的特征,运动跟踪和光线投射。使用LiDAR扫描仪,您可以重建场景,甚至在没有照明的环境中,或在一个房间里有白色的墙壁,没有任何特征。周围环境的3d重建已经成为可能,在ARKit 6.0感谢sceneReconstruction示例属性。有一个重建的网格,你的墙壁是'现在,把任何物体藏在真实的的墙后面都超级容易。
要在ARKit 6.0中激活sceneReconstruction示例属性,请使用以下代码:

@IBOutlet var arView: ARView!

arView.automaticallyConfigureSession = false

guard ARWorldTrackingConfiguration.supportsSceneReconstruction(.mesh)
else { return }

let config = ARWorldTrackingConfiguration()
config.sceneReconstruction = .mesh

arView.debugOptions.insert([.showSceneUnderstanding])
arView.environment.sceneUnderstanding.options.insert([.occlusion])
arView.session.run(config)

此外,如果您正在使用SceneKit,请尝试以下方法:

@IBOutlet var sceneView: ARSCNView!

func renderer(_ renderer: SCNSceneRenderer, 
          nodeFor anchor: ARAnchor) -> SCNNode? {

    guard let meshAnchor = anchor as? ARMeshAnchor 
    else { return nil }

    let geometry = SCNGeometry(arGeometry: meshAnchor.geometry)

    geometry.firstMaterial?.diffuse.contents = 
                            colorizer.assignColor(to: meshAnchor.identifier)
‍
    let node = SCNNode()
    node.name = "Node_\(meshAnchor.identifier)"
    node.geometry = geometry
    return node
}

func renderer(_ renderer: SCNSceneRenderer,
          didUpdate node: SCNNode,
              for anchor: ARAnchor) {

    guard let meshAnchor = anchor as? ARMeshAnchor 
    else { return }

    let newGeometry = SCNGeometry(arGeometry: meshAnchor.geometry)

    newGeometry.firstMaterial?.diffuse.contents = 
                               colorizer.assignColor(to: meshAnchor.identifier)

    node.geometry = newGeometry
}

下面是SCNGeometrySCNGeometrySource扩展:

extension SCNGeometry {
    convenience init(arGeometry: ARMeshGeometry) {
        let verticesSource = SCNGeometrySource(arGeometry.vertices, 
                                               semantic: .vertex)
        let normalsSource = SCNGeometrySource(arGeometry.normals, 
                                               semantic: .normal)
        let faces = SCNGeometryElement(arGeometry.faces)
        self.init(sources: [verticesSource, normalsSource], elements: [faces])
    }
}

extension SCNGeometrySource {
    convenience init(_ source: ARGeometrySource, semantic: Semantic) {
        self.init(buffer: source.buffer, vertexFormat: source.format,
                                             semantic: semantic,
                                          vertexCount: source.count,
                                           dataOffset: source.offset,
                                           dataStride: source.stride)
    }
}

...以及SCNGeometryElementSCNGeometryPrimitiveType扩展名:

extension SCNGeometryElement {
    convenience init(_ source: ARGeometryElement) {
        let pointer = source.buffer.contents()
        let byteCount = source.count * 
                        source.indexCountPerPrimitive * 
                        source.bytesPerIndex
        let data = Data(bytesNoCopy: pointer, 
                              count: byteCount, 
                        deallocator: .none)
        self.init(data: data, primitiveType: .of(source.primitiveType),
                             primitiveCount: source.count,
                              bytesPerIndex: source.bytesPerIndex)
    }
}

extension SCNGeometryPrimitiveType {
    static func of(type: ARGeometryPrimitiveType) -> SCNGeometryPrimitiveType {
        switch type {
            case .line: return .line
            case .triangle: return .triangles
        }
    }
}

相关问题