You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

RealityKit实现点击USDZ模型部位弹出名称及详情的方法

iOS RealityKit 实现USDZ模型特定部位点击识别与弹窗提示

核心实现思路

利用RealityKit的射线检测功能,点击屏幕时获取命中的模型子实体,通过子实体的唯一名称(建模时提前设置)识别具体部位,进而弹出对应描述弹窗。


具体实现步骤

1. 预处理USDZ模型

在Blender、Maya等建模软件中,给牙齿模型的每个需要识别的部位设置唯一且易区分的名称(比如upper_incisor_left、lower_molar_right),导出USDZ时保留这些名称,确保加载到RealityKit后每个子实体都带有对应的name属性。

2. 添加点击手势与射线检测

给ARView添加点击手势识别器,在回调中调用arView.entity(at:)获取点击位置命中的实体,该方法会返回点击路径上最上层的子实体(即你点击的具体牙齿部位)。

3. 匹配部位名称并弹窗

根据命中实体的name,匹配预设的部位描述,用UIAlertController弹出提示。


修改后的完整代码

import ARKit
import UIKit
import RealityKit

class ARViewController_plane: UIViewController {
    
    let arView = ARView()
    var modelEntity: ModelEntity?
    
    override func loadView() {
        super.loadView()
        view = arView
        
        // 加载模型
        modelEntity = createModel()
        guard let model = modelEntity else { return }
        
        // 放置模型
        placeModel(model: model)
        
        // 设置手势(缩放、旋转+新增点击)
        installGestures(on: model)
        
        // 启动AR会话
        let configuration = ARWorldTrackingConfiguration()
        configuration.planeDetection = .horizontal
        arView.session.run(configuration)
    }
    
    func createModel() -> ModelEntity? {
        do {
            return try ModelEntity.loadModel(named: "tsmile1.usdz")
        } catch {
            print("模型加载失败: \(error.localizedDescription)")
            return nil
        }
    }
    
    func placeModel(model: ModelEntity) {
        let planeAnchor = AnchorEntity(world: SIMD3(0, 0, 0))
        planeAnchor.addChild(model)
        arView.scene.addAnchor(planeAnchor)
    }
    
    func installGestures(on object: ModelEntity) {
        // 缩放手势
        object.generateCollisionShapes(recursive: true)
        arView.installGestures([.scale], for: object)
        
        // 自定义旋转手势
        let rotationGesture = UIPanGestureRecognizer(target: self, action: #selector(handleRotationGesture(_:)))
        arView.addGestureRecognizer(rotationGesture)
        
        // 点击手势(新增)
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleModelTap(_:)))
        arView.addGestureRecognizer(tapGesture)
    }
    
    @objc func handleRotationGesture(_ gesture: UIPanGestureRecognizer) {
        guard let model = modelEntity else { return }
        let translation = gesture.translation(in: arView)
        let rotationAngle = Float(translation.x) * 0.001
        
        var currentTransform = model.transform
        let newRotation = simd_quatf(angle: rotationAngle, axis: [0, 0, 1])
        currentTransform.rotation = simd_mul(currentTransform.rotation, newRotation)
        model.transform = currentTransform
        
        // 重置手势位移,避免旋转累计过快
        if gesture.state == .ended {
            gesture.setTranslation(.zero, in: arView)
        }
    }
    
    // 新增:点击模型部位的处理方法
    @objc func handleModelTap(_ gesture: UITapGestureRecognizer) {
        let tapLocation = gesture.location(in: arView)
        
        // 射线检测获取命中的实体
        guard let hitEntity = arView.entity(at: tapLocation) else { return }
        
        // 根据实体名称判断部位,弹出对应描述
        var partDescription = ""
        switch hitEntity.name {
        case "upper_incisor_left":
            partDescription = "左上中切牙:负责切割食物,是口腔中最显眼的牙齿之一。"
        case "lower_molar_right":
            partDescription = "右下磨牙:承担主要的咀嚼功能,表面有复杂的咬合面。"
        // 这里添加更多部位的名称与描述匹配
        default:
            partDescription = "未知部位"
        }
        
        // 弹窗展示描述
        let alert = UIAlertController(title: "牙齿部位信息", message: partDescription, preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "确定", style: .default))
        present(alert, animated: true)
    }
}

关键代码说明

  • arView.entity(at: tapLocation):核心API,通过点击位置发射射线,返回命中的第一个实体(即点击的具体部位)。
  • hitEntity.name:依赖建模时给子部件设置的名称,必须保证USDZ模型导出时保留这些名称。
  • object.generateCollisionShapes(recursive: true):必须设为true,确保射线检测能遍历到所有子实体。

内容的提问来源于stack exchange,提问作者zzhzzh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 04:57:35