如何解决ARKit + SceneKit:使用重建的物理场景?
我将 ARKit 与 SceneKit 结合使用,并希望让我的 3D 对象与具有激光雷达传感器 (config.sceneReconstruction = .mesh
) 的设备创建的 reconstructed scene 进行物理交互。例如,让虚拟球从重建场景的几何形状反弹。
在 RealityKit 中,这似乎可以使用 sceneUnderstanding
:
arView.environment.sceneUnderstanding.options.insert(.physics)
如何在使用 SceneKit 时达到同样的效果?
解决方法
据我所知,没有使用 SceneKit 启用此功能的内置支持。但是,您可以使用 ARKit 创建的 ARMeshAnchor
轻松组合自定义解决方案。
首先,配置 ARKit 以启用场景重建:
let config = ARWorldTrackingConfiguration()
if ARWorldTrackingConfiguration.supportsSceneReconstruction(.mesh) {
config.sceneReconstruction = .mesh
} else {
// Handle device that doesn't support scene reconstruction
}
// and enable physics visualization for debugging
sceneView.debugOptions = [.showPhysicsShapes]
然后在您的 ARSCNViewDelegate
中使用 renderer nodeFor
为新创建的 ARMeshAnchor
实例创建一个 Scenekit 节点:
func renderer(_ renderer: SCNSceneRenderer,nodeFor anchor: ARAnchor) -> SCNNode? {
guard let meshAnchor = anchor as? ARMeshAnchor else {
return nil
}
let geometry = createGeometryFromAnchor(meshAnchor: meshAnchor)
// Optionally hide the node from rendering as well
geometry.firstMaterial?.colorBufferWriteMask = []
let node = SCNNode(geometry: geometry)
// Make sure physics apply to the node
// You must used concavePolyhedron here!
node.physicsBody = SCNPhysicsBody(type: .static,shape: SCNPhysicsShape(geometry: geometry,options: [.type: SCNPhysicsShape.ShapeType.concavePolyhedron]))
return node
}
// Taken from https://developer.apple.com/forums/thread/130599
func createGeometryFromAnchor(meshAnchor: ARMeshAnchor) -> SCNGeometry {
let meshGeometry = meshAnchor.geometry
let vertices = meshGeometry.vertices
let normals = meshGeometry.normals
let faces = meshGeometry.faces
// use the MTL buffer that ARKit gives us
let vertexSource = SCNGeometrySource(buffer: vertices.buffer,vertexFormat: vertices.format,semantic: .vertex,vertexCount: vertices.count,dataOffset: vertices.offset,dataStride: vertices.stride)
let normalsSource = SCNGeometrySource(buffer: normals.buffer,vertexFormat: normals.format,semantic: .normal,vertexCount: normals.count,dataOffset: normals.offset,dataStride: normals.stride)
// Copy bytes as we may use them later
let faceData = Data(bytes: faces.buffer.contents(),count: faces.buffer.length)
// create the geometry element
let geometryElement = SCNGeometryElement(data: faceData,primitiveType: toSCNGeometryPrimitiveType(faces.primitiveType),primitiveCount: faces.count,bytesPerIndex: faces.bytesPerIndex)
return SCNGeometry(sources: [vertexSource,normalsSource],elements: [geometryElement])
}
最后,每当 ARSCNViewDelegate renderer didUpdate:
函数中重建的几何体发生变化时,更新场景节点:
func renderer(_ renderer: SCNSceneRenderer,didUpdate node: SCNNode,for anchor: ARAnchor) {
guard let meshAnchor = anchor as? ARMeshAnchor else {
return
}
let geometry = SCNGeometry.fromAnchor(meshAnchor: meshAnchor,setColors: false)
geometry.firstMaterial?.colorBufferWriteMask = []
node.geometry = geometry
node.physicsBody!.physicsShape = SCNPhysicsShape(geometry: geometry,options: [.type: SCNPhysicsShape.ShapeType.concavePolyhedron])
}
您在 SceneKit 中创建的任何物理对象现在都应该能够与重建的场景交互:
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。