首页 > 其他分享 >iOS ARKit 中的射线检测

iOS ARKit 中的射线检测

时间:2024-01-16 17:11:07浏览次数:31  
标签:ARRaycastQuery 碰撞 检测 iOS 射线 ARKit let 方法

  • 射线检测简介    

  射线检测 Ray casting,直译为射线投射,通常我们根据它的作用称为射线检测。射线检测是在3D数字世界选择某个特定物体常用的一种技术,如在3D、VR 游戏中检测子弹命中敌人情况或者从地上捡起一支枪,这都要用到射线检测,射线检测是在3D 数字空间中选择虚拟物体最基本的方法。

      在 AR 中,当检测并可视化一个平面后,如果需要在平面上放置虚拟物体,就会碰到在平面上什么位置放置虚拟物体的问题,因为检测到的平面是三维的,而手机/平板显示屏幕却是二维的,如何在二维平面上选择三维放置点呢?解决这个问题的通常做法就是射线检测。

      射线检测的基本思路是在三维空间中从一个点沿一个方向发射出一条无限长的射线,在射线的方「上,一旦与添加了碰撞器的物体发生碰撞,则产生一个碰撞检测对象。因此,可以利用射线实现子弹击中标的检测,也可以用射线检测发生碰撞的位置,例如,我们可以从屏幕中用户单击点的位置,利用摄像机(AR中就是我们的眼睛)的位置来构建一条射线,与场景中的平面进行碰撞检测,如果发生碰撞,则返回碰撞的位置,这样就可以在检测到的平面上放置虚拟物体了,

     射线检测的具体做法是检测用户单击屏幕的操作,以单击的位置为基准,连接该位置与摄像机就可将两点构成一条直线。从摄像机位置出发,通过单击点就可以构建一条射线用该射线与场景中的物体进行碰撞检测,如果发生碰撞则返回碰撞对象,这就是AR 中射线检测的技术原理

  • ARKit 中的射线检测

ARKit 在 ARView、Scene、ARSession 类中都提供了射线检测方法,这些方法灵活多样,不仅可以满足对场景中虚拟物体的检测,也可以实现对检测到的平面、特征点、场景几何网格的碰撞检测,极大地方便了开发者的使用。ARView 中提供的射线检测方法如表13所示。

                                                                                                        表13 ARView 中提供的射线检测方法

射线检测方法

描述

makeRaycastQuery(from: CGPoint, allowing: ARRaycastQuery.Target, alignment: ARRaycastQuery. TargetAlignment) — >ARRaycastQuery?

这是一个射线检测辅助方法,用于构建一个 ARView 射线检测请求

raycast (from: CGPoint, allowing: ARRaycastQuery. Target , alignment: ARRaycastQuery.TargetAlignment)—>[ARRaycastResult]

投射一条从摄像机到场景中的射线,返回射线检测结果

trackedRaycast(from: CGPoint, allowing: ARRaycastQuery. Target, alignment: ARRaycastQuery. TargetAlignment, updateHandler: ARRaycastResult]) -> Void) -> ARTrackedRaycast?

投射一条从摄像机到场景中的射线,进行射线检测并返回结果。与 raycast()方法不同的是,该方法会对投射的射线进行跟踪以便优化检测结果

 

 

 

 

 

 

 

 

 

 

 

 

 

            表13 提供的射线方法中,from 参数为屏幕单击位置;allowing 参数 ARRaycastQuery. Target 类型,可以为 estimatedPlane(ARKit 估计的平面,但此时位置与尺寸都不稳定)、existingPlaneGeometry(位置与尺寸都稳定的平面)、existingPlaneInfinite(稳定平面所在的无限平面)3个值中的一个或者几个(多个时使用或(I)连接);alignment 参数为 ARRaycastQuery. TargetAlignment 类型,可以为 horizontal(水平平面)、vertical(垂直平面)、any(水平平面、垂直平面、场景几何)。进行射线检测后,检测结果为 ARRaycastResult 数组。当没有发生碰撞时,该数组为nil,如果发生碰童,则所有发生碰撞的信息(碰撞位置、碰撞对象名、距离等)都会存储在这个数组中。在大多数情况下,数组序号为0的结果为我们所需要的结果(即离使用者最近的碰撞对象)。ARView 中提供的射线检测方法以当前设备屏幕中的2D坐标为起始点向场景中发射射线进行碰撞检测,因此非常方便手势操作使用。

    scene也提供了射线检测方法如下表所示

射线检测方法

描述

raycast (origin: SIMD3 < Float >, direction: SIMD3 < Float >, length: Float, query: CollisionCastQueryType, mask: CollisionGroup, relativeTo: Entity?) - >

[CollisionCast Hit]

在场景中指定起始点、方向、长度构建射线,并可指定碰撞类型等其他属性的射线检测方法

 

raycast(from: SIMD3 < Float >, to: SIMD3 < Float >, query: CollisionCastQuery lype, mask: CollisionGroup, relativeTo: Entity?) -> [CollisionCastHit]

在场景中两点之间构建射线,可指定碰撞类型等其他属性的射线检测方法

convexCast ( convexShape: ShapeResource, fromPosition: SIMD3 < Float >, fromOrientation: simd_ quatf, toPosition: SIMD3 < Float >, toOrientation: simd quatf, query: CollisionCastQueryType, mask: CollisionGroup, relativeTo: Entity?) ->

[CollisionCast Hit]

在两个物体之间构建射线,可实现更复杂的射线检测操作

 

 

 

 

   从射线检测方法参数可以看出,Scene 中的射线检测方法更侧重于在场景中通过指定位置、指定方向、指定物体、指定碰撞器等构建更复杂的射线检测需求,实现更具体的射线检测。因此,Scene 中的射线检测方法特别适合于在 AR场景中一个虚拟物体向另一个虚拟物体进行碰撞检测的场合,如在AR场景中,一个机器人向一个怪物发射子弹。

    ARSession 中提供的射线检测方法如表15所示。与 ARView 中的射线检测方法类似,ARSession 中的射线检测方法也主要处理从屏幕到场景的射线检测。

                                                              表15 ARSession 中提供的射线检测方法

射线检测方法

描述

raycast (ARRaycastQuery) ->[ARRaycastResult]

根据射线检测请求执行射线检测操作

trackedRaycast(ARRaycastQuery, updateHandler: ([ARRaycastResult]) ->

Void) -> ARTrackedRaycast?

根据射线检测消求执行射线检测操作。与

raycast()方法不同的是,该方法会对投射的射线进行跟踪以便优化检测结果

 

 

 

 

 

 

  • ARKit射线检测实例代码
    import SwiftUI
    import RealityKit
    import ARKit
    import Combine
    
    struct RayCheckingAndGestureView : View {
        var body: some View {
            return ARViewContainer5().edgesIgnoringSafeArea(.all)
        }
    }
    
    struct ARViewContainer5: UIViewRepresentable {
        let arView = ARView(frame: .zero)
        let dele = ARViewSessionDelegate()
        
        func makeUIView(context: Context) -> ARView {
            
            
            dele.containner = self
            let config = ARWorldTrackingConfiguration()
            config.planeDetection = .horizontal
            arView.session.run(config, options:[ ])
            arView.session.delegate = dele
            createPlane()
            arView.setupGestures()
            return arView
        }
        
        func updateUIView(_ uiView: ARView, context: Context) {
        }
        
        func createPlane(){
            func createPlane(){
                let planeAnchor = AnchorEntity(plane:.horizontal)
                do {
                    planeMaterial1.color = try SimpleMaterial.BaseColor(tint:UIColor.yellow.withAlphaComponent(0.9999), texture: MaterialParameters.Texture(TextureResource.load(named: "AR_Placement_Indicator.png")))
                    planeAnchor.addChild(planeEntity1)
                    self.arView.scene.addAnchor(planeAnchor)
                } catch {
                    print("找不到文件")
                }
            }
        }
        
        
    }
    
    var planeMesh1 = MeshResource.generatePlane(width: 0.15, depth: 0.15)
    var planeMaterial1 = SimpleMaterial(color:.white,isMetallic: false)
    var planeEntity1 : ModelEntity = ModelEntity(mesh:planeMesh1,materials:[planeMaterial1])
    var planeAnchor1 = AnchorEntity()
    var objectPlaced1 = false
    var raycastResult1 : ARRaycastResult?
    
    
    extension ARView {
        func setupGestures1() {
          let tap = UITapGestureRecognizer(target: self, action: #selector(handleTap))
            self.addGestureRecognizer(tap)
        }
        
        @objc func handleTap1(_ sender: UITapGestureRecognizer? = nil) {
            if objectPlaced1 {return}
            let cubeMesh = MeshResource.generateBox(size: 0.1)
            let cubeMaterial = SimpleMaterial(color:.red,isMetallic: false)
            let cubeEntity = ModelEntity(mesh:cubeMesh,materials:[cubeMaterial])
            let cubeAnchor = AnchorEntity(raycastResult:raycastResult1!)
            cubeAnchor.addChild(cubeEntity)
            scene.addAnchor(cubeAnchor)
            planeEntity1.removeFromParent()
           
            objectPlaced1 = true
    
        }
    }
    
    class ARViewSessionDelegate : NSObject, ARSessionDelegate{
        
        var containner: ARViewContainer5?
        
        public func session(_ session: ARSession, didUpdate frame: ARFrame){
            if objectPlaced1 {return}
            guard let arView = containner?.arView, let result = arView.raycast(from: arView.center, allowing: .estimatedPlane, alignment: .horizontal).first else {
                return
            }
            raycastResult1 = result
            planeEntity1.setTransformMatrix(result.worldTransform, relativeTo: nil)
        }
    /*
        public func session(_ session: ARSession, didUpdate frame: ARFrame){
            if objectPlaced {return}
            guard let raycastQuery = self.makeRaycastQuery(from: self.center,
                                                         allowing: .estimatedPlane,
                                                        alignment: .horizontal) else {
                return
            }
    
            guard let result = self.session.raycast(raycastQuery).first else {
                return
            }
            raycastResult = result
            planeEntity!.setTransformMatrix(result.worldTransform, relativeTo: nil)
        }
        */
       
    }
    

     

 

标签:ARRaycastQuery,碰撞,检测,iOS,射线,ARKit,let,方法
From: https://www.cnblogs.com/duzhaoquan/p/17968109

相关文章

  • iSpoofer iOS官方網站免費下載以及如何安裝 iSpoofer Android替代品 iSpoofer安全嗎
    當您喜歡玩PokemonGo時,您可以使用iSpoofer來獲得不錯的增強效果。iSpoofer可以輕鬆地在遊戲中添加操縱桿,甚至可以實現免費傳送。其他吸引人的功能包括IV檢查、GPS追蹤、自動行走、快速神奇寶貝捕捉技巧、增強投擲等。最重要的是,您可以獲得一張地圖,可以密切關注周圍的一......
  • iOS ARKit 三大类 ARSession ARAnchor ARFrame
    ARSessionARSession(AR会话)是ARKit中最重要的概念之一,其主要的功能是管理AR应用的状态和整个周期,是ARKitAPI的主要人口。ARSession整合了底层的所有技术并为开发者提供程序界面,这些技术包括从设备运动传感器硬件取数据、捕获摄像头图像数据并进行分析、控制虛拟场景摄像机与硬......
  • iOS ARKit 三大基础能力
    ARKit三大基础能力   ARKit整合了SLAM、计算机视觉、机器学习、传感器融合、表面估计、光学校准、特征匹配、非线性优化等大量低层技术,提供给开发者简洁易用的程序界面。ARKit提供的功能总体可以分为3个部分:运动跟踪、场景理解、渲染,1.运动跟踪运动跟踪可以实时跟......
  • iOS ARKit 显示引导示图、添加正方体
    ARKit概述2017年,在WWDC(WorldWideDevelopersConference,苹果全球开发者大会)上,苹果公司了增强现实开发套件ARKit。ARKit一推出即在科技圈引发极大关注,一方面是苹果公司在科技影响力,另一方面更重要的是ARKit在秘动端实现的堪称惊艳的AR效果。ARKit的面世,直接术带到了亿万用......
  • ios如何连接代理?
    1.打开设置,点击无线局限网。2.打开无限局域网开关,连接WIFI,点击已连接WIFI的右侧小图标。3.点击配置代理界面,选择“手动”。4.点开辅助工具,复制局域网的代理地址、端口,填入服务器、端口的输入框中,并打开认证开关。5.填写【用户名、密码】在对应的输入框,点击存储。6.......
  • Vue 3 + TypeScript + Vite + Element-Plus + Router + Axios + Pinia项目搭建(内含完
    Vue3+TypeScript+Vite+Element-Plus+Router+Axios+Pinia项目搭建(内含完整架构)安装Vue3+ts+vitenpminitvite@latest选择y,新建项目名称,选择vue,选择vue-ts下载完成后执行以下命令行cd新建的项目名称npminpmrundev安装Element-Plusnpminstallelement-plus-......
  • 启用DoH(DNS-over HTTPS)在Windows、Android、IOS平台
    做个备忘录,记录下主力设备Win11、安卓、IOS、路由器、浏览器配置DoH(DNS-overHTTPS)的过程Windows11设置-网络和Internet-WLAN-硬件属性-DNS服务器分配Win11原生支持的DoH服务:IPv4Google:8.8.8.8and8.8.4.4Cloudflare:1.1.1.1and1.0.0.1Quad9:9.9.9.9and149.112......
  • 如何屏蔽苹果iOS 17软件自动更新,去除更新通知和标记
    亲爱的小伙伴们大家好!我是咕噜铁蛋!,你是否经常被iOS系统的更新提示所困扰?每次看到那个小红点或者数字提示,心里总是纠结万分。更新吧,怕新系统不如旧系统稳定;不更新吧,那个小红点或数字总是如影随形,让人心烦。今天,我将为你详细解读如何屏蔽iOS17的软件自动更新,让你从此远离更新烦......
  • axios发送get、post请求
    1.环境安装//nodejs环境//npminstallaxios2.axios发送get请求constaxios=require('axios')consturl="xxx.xxx.xxx";constheaders={}axios.get(url,{headers}).then(function(response){console.log(response.data)r......
  • XCODE IOS 静态链接库替换升级
    XCODE 版本15.2. 一个很久需求没更新的IOS应用,近来有新需求要开发。拉下代码运行,出现了个BAD_ACCESS错误。出错的位置位于一个调用的第三方的.a静态库内部。因为调用代码并没有修改,很容易想到可能XCODE相关升级,导致的问题。由于是第三方的一个.a动态库,兼容问题,......