ARKit应用实现平面检测自动生成3D桌面对象的方案求助
ARKit平面检测时自动生成桌子模型的解决方案
问题排查
你之前在平面检测回调中生成模型失败、模型出现在屏幕顶部,核心原因有两个:
- 未在平面检测回调中正确加载并定位桌子模型,仅添加了网格平面
- 若直接将桌子添加到根节点,未利用ARKit锚点节点的坐标系绑定,导致位置计算错误
修正后的完整代码
// 添加标记,避免同一平面重复生成桌子 private var hasGeneratedTable = false override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { print("Tapped") if let touch = touches.first { let touchLocation = touch.location(in: sceneView) let results = sceneView.hitTest(touchLocation, types: .existingPlaneUsingExtent) if let hitResults = results.first { let diceScene = SCNScene(named: "art.scnassets/Table.scn")! if let diceNode = diceScene.rootNode.childNode(withName: "Table", recursively: true) { diceNode.position = SCNVector3( x: hitResults.worldTransform.columns.3.x, y: hitResults.worldTransform.columns.3.y, z: hitResults.worldTransform.columns.3.z) sceneView.scene.rootNode.addChildNode(diceNode) print("Rendered") } } } } func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) { guard let planeAnchor = anchor as? ARPlaneAnchor, !hasGeneratedTable else { return } // 生成网格平面(保留原有逻辑) let plane = SCNPlane(width: CGFloat(planeAnchor.extent.x), height: CGFloat(planeAnchor.extent.z)) let planeNode = SCNNode() planeNode.position = SCNVector3(x: planeAnchor.center.x, y: 0, z: planeAnchor.center.z) planeNode.transform = SCNMatrix4MakeRotation(-Float.pi/2, 1, 0, 0) let gridMaterial = SCNMaterial() gridMaterial.diffuse.contents = UIImage(named: "art.scnassets/grid.png") plane.materials = [gridMaterial] planeNode.geometry = plane node.addChildNode(planeNode) // 加载并生成桌子模型 guard let tableScene = SCNScene(named: "art.scnassets/Table.scn"), let tableNode = tableScene.rootNode.childNode(withName: "Table", recursively: true) else { print("Failed to load table model") return } // 设置桌子位置:与平面锚点中心对齐,y值匹配平面高度 tableNode.position = SCNVector3( x: planeAnchor.center.x, y: planeAnchor.center.y, z: planeAnchor.center.z ) // 将桌子添加到锚点对应的节点,确保平面更新时模型同步跟踪 node.addChildNode(tableNode) hasGeneratedTable = true print("Table automatically generated on detected plane") } // 可选:处理平面更新,避免模型位置偏移 func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) { guard let planeAnchor = anchor as? ARPlaneAnchor, let planeNode = node.childNodes.first, let plane = planeNode.geometry as? SCNPlane else { return } // 更新网格平面的大小和位置 plane.width = CGFloat(planeAnchor.extent.x) plane.height = CGFloat(planeAnchor.extent.z) planeNode.position = SCNVector3(x: planeAnchor.center.x, y: 0, z: planeAnchor.center.z) }
关键注意事项
- 避免重复生成:通过
hasGeneratedTable标记控制只生成一次桌子,防止ARKit持续检测平面时重复添加 - 坐标系绑定:将桌子节点添加到锚点对应的
node上,而非直接加到根节点,这样平面位置更新时桌子会同步跟随 - 位置校准:使用
planeAnchor.center.y作为桌子的y坐标,确保桌子刚好落在检测到的平面上,解决模型出现在屏幕顶部的问题 - 模型加载校验:添加加载失败的打印日志,方便排查模型文件路径或命名错误
内容的提问来源于stack exchange,提问作者user19727360
相关产品推荐
相关产品推荐

