【iOS ARKit】PhysicsBodyComponent

     在学习完 RealityKit 进行物理模拟的相关理论知识后,下面通过使用 PhysicsBodyComponent 组件进行物理模拟演示,主要代码如下所示,稍后对代码进行详细解析。

//
//  PhysicsBodyView.swift
//  ARKitDeamo
//
//  Created by zhaoquan du on 2024/3/14.
//import SwiftUI
import ARKit
import RealityKitstruct PhysicsBodyView: View {var body: some View {PhysicsBodyViewContainer().navigationTitle("物理模拟").edgesIgnoringSafeArea(.all)}
}
struct PhysicsBodyViewContainer:UIViewRepresentable {func makeCoordinator() -> Coordinator {Coordinator()}func makeUIView(context: Context) -> some ARView {let arView = ARView(frame: .zero)let config = ARWorldTrackingConfiguration()config.planeDetection = .horizontalcontext.coordinator.arView = arViewarView.session.delegate  = context.coordinatorarView.session.run(config)return arView}func updateUIView(_ uiView: UIViewType, context: Context) {}class Coordinator: NSObject, ARSessionDelegate{var sphereEntity : ModelEntity!var arView:ARView? = nillet gameController = GameController()func session(_ session: ARSession, didAdd anchors: [ARAnchor]) {guard let anchor = anchors.first as? ARPlaneAnchor,let arView = arView else{return}let planeAnchor = AnchorEntity(anchor:anchor)//sample1let boxCollider: ShapeResource = .generateBox(size: [0.1,0.2,1])let box: MeshResource = .generateBox(size: [0.1,0.2,1], cornerRadius: 0.02)let boxMaterial = SimpleMaterial(color: .yellow,isMetallic: true)let boxEntity = ModelEntity(mesh: box, materials: [boxMaterial], collisionShape: boxCollider, mass: 0.05)boxEntity.physicsBody?.mode = .dynamicboxEntity.name = "Box"boxEntity.transform.translation = [0.2,planeAnchor.transform.translation.y+0.15,0]let sphereCollider : ShapeResource = .generateSphere(radius: 0.05)let sphere: MeshResource = .generateSphere(radius: 0.05)let sphereMaterial = SimpleMaterial(color:.red,isMetallic: true)sphereEntity = ModelEntity(mesh: sphere, materials: [sphereMaterial], collisionShape: sphereCollider, mass: 0.04)sphereEntity.physicsBody?.mode = .dynamicsphereEntity.name = "Sphere"sphereEntity.transform.translation = [-0.3,planeAnchor.transform.translation.y+0.15,0]sphereEntity.physicsBody?.material = .generate(friction: 0.001, restitution: 0.01)//平面let plane :MeshResource = .generatePlane(width: 1.2, depth: 1.2)let planeCollider : ShapeResource = .generateBox(width: 1.2, height: 0.01, depth: 1.2)let planeMaterial = SimpleMaterial(color:.gray,isMetallic: false)let planeEntity = ModelEntity(mesh: plane, materials: [planeMaterial], collisionShape: planeCollider, mass: 0.01)planeEntity.physicsBody?.mode = .static//静态平面不具备碰撞性planeEntity.physicsBody?.material = .generate(friction: 0.001, restitution: 0.1)planeAnchor.addChild(planeEntity)planeAnchor.addChild(boxEntity)planeAnchor.addChild(sphereEntity)//添加碰撞订阅let subscription = arView.scene.subscribe(to: CollisionEvents.Began.self, { event inprint("box发生碰撞")print("entityA.name: \(event.entityA.name)")print("entityB.name: \(event.entityB.name)")print("Force : \(event.impulse)")print("Collision Position: \(event.position)")})gameController.collisionEventStreams.append(subscription)arView.scene.addAnchor(planeAnchor)let gestureRecognizers = arView.installGestures(.translation, for: sphereEntity)if let gestureRecognizer = gestureRecognizers.first as? EntityTranslationGestureRecognizer {gameController.gestureRecognizer = gestureRecognizergestureRecognizer.removeTarget(nil, action: nil)gestureRecognizer.addTarget(self, action: #selector(handleTranslation))}arView.session.delegate = nilarView.session.run(ARWorldTrackingConfiguration())}@objc func handleTranslation(_ recognizer: EntityTranslationGestureRecognizer){guard let ball = sphereEntity else { return }let settings = gameController.settingsif recognizer.state == .ended || recognizer.state == .cancelled {gameController.gestureStartLocation = nilball.physicsBody?.mode = .dynamicreturn}guard let gestureCurrentLocation = recognizer.translation(in: nil) else { return }guard let gestureStartLocation = gameController.gestureStartLocation else {gameController.gestureStartLocation = gestureCurrentLocationreturn}let delta = gestureStartLocation - gestureCurrentLocationlet distance = ((delta.x * delta.x) + (delta.y * delta.y) + (delta.z * delta.z)).squareRoot()if distance > settings.ballPlayDistanceThreshold {gameController.gestureStartLocation = nilball.physicsBody?.mode = .dynamicreturn}//ball.physicsBody?.mode = .kinematiclet realVelocity = recognizer.velocity(in: nil)let ballParentVelocity = ball.parent!.convert(direction: realVelocity, from: nil)var clampedX = ballParentVelocity.xvar clampedZ = ballParentVelocity.z// 夹断if clampedX > settings.ballVelocityMaxX {clampedX = settings.ballVelocityMaxX} else if clampedX < settings.ballVelocityMinX {clampedX = settings.ballVelocityMinX}// 夹断if clampedZ > settings.ballVelocityMaxZ {clampedZ = settings.ballVelocityMaxZ} else if clampedZ < settings.ballVelocityMinZ {clampedZ = settings.ballVelocityMinZ}let clampedVelocity: SIMD3<Float> = [clampedX, 0.0, clampedZ]//ball.physicsMotion?.linearVelocity = clampedVelocityball.addForce(clampedVelocity*0.1, relativeTo: nil)}}
}#Preview {PhysicsBodyView()
}

      在代码清单中,实现的功能如下:

   (1)构建模拟环境。

   (2)通过施加力,对物体运动进行物理模拟。

     在功能1中,我们通过 session(_ session:ARSession, didAdd anchors: [ARAnchor])方法对平面检测情况进行监视,当 ARKit 检测到符合要求的水平平面后,手动生成一个长方体、一个球体、一个承载这两个物体的平面,构建了基本的模拟环境,如图所示。由于生成的长方体与球体均是带有质量与碰撞器的实体,在使用物理引擎时,它们会在重力作用下下坠,生成的平面主要用于承载这两个物体。在设置好物理模拟相关属性后,我们还订阅(subscriptions)了长方体的碰撞事件,当长方体与其他物体发生碰撞时会打印出发生碰撞的两个实体对象名称、碰撞时的受力和碰撞位置信息。

     在功能2中,为方便控制,我们使用了 RealityKit 中的平移手势(Entity Lranslation GrestureRecogniner),通过计算使用者手指在犀幕上滑动的速度生威作用力,并将该作用力施加在球体上,通过施加作用力就可以观察球体与长方体在物理引擎作用下的运动效果(为防止施加的力过大,我们使用了GameSettings结构体并定义了几个边界值,具体可以参看本节源码)。

     编译后测试,使用平移手势操作球体,当球体撞击到长方体后,会发生物理交互并触发长方体的碰撞事件。读者可以修改使用不同的物理参数和碰撞形状,看一看物理参数如何影响物体的运动,以及碰撞形状如何影响碰撞位置。

     这个例子综合演示了物理参数和属性的设置、物理事件的处理、物理材质对物理模拟的影响,同时也是最简单的物理引擎使用案例,没有使用 group 和 mask设置碰撞分组,仅演示了 PhysicsBodyComponent组件的最基本使用方法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/542195.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

浅易理解:非极大抑制NMS

什么是非极大抑制NMS 非极大值抑制&#xff08;Non-Maximum Suppression&#xff0c;简称NMS&#xff09;是一种在计算机视觉和图像处理领域中广泛使用的后处理技术&#xff0c;特别是在目标检测任务中。它的主要目的是解决目标检测过程中出现的重复检测问题&#xff0c;即对于…

租房网站|基于springboot框架+ Mysql+Java+B/S架构的租房网站设计与实现(可运行源码+数据库+设计文档+部署说明)

推荐阅读100套最新项目 最新ssmjava项目文档视频演示可运行源码分享 最新jspjava项目文档视频演示可运行源码分享 最新Spring Boot项目文档视频演示可运行源码分享 目录 前台功能效果图 用户功能模块 管理员功能登录前台功能效果图 系统功能设计 数据库E-R图设计 lunwen参…

三种方式使用纯 CSS 实现星级评分

本文介绍三种使用纯 CSS 实现星级评分的方式。每种都值得细品一番~ 五角星取自 Element Plus 的 svg 资源 <svg xmlns"http://www.w3.org/2000/svg" viewBox"0 0 1024 1024" style""><pathfill"currentColor"d"M283.84 …

分析型数据库的主要使用场景有哪些?

如今数据已经成为了企业和组织的核心资产。如何有效地管理和利用这些数据&#xff0c;成为了决定竞争力的关键。分析型数据库作为数据处理领域的重要工具&#xff0c;为各行各业提供了强大的数据分析和洞察能力。基于分析型数据库&#xff08;Apache Doris &#xff09;构建的现…

【机器学习】机器学习创建算法第2篇:K-近邻算法【附代码文档】

机器学习&#xff08;算法篇&#xff09;完整教程&#xff08;附代码资料&#xff09;主要内容讲述&#xff1a;机器学习算法课程定位、目标&#xff0c;K-近邻算法&#xff0c;1.1 K-近邻算法简介&#xff0c;1.2 k近邻算法api初步使用定位,目标,学习目标,1 什么是K-近邻算法,…

Trie树(详解+例题)

1、介绍Trie树 Trie树&#xff0c;即字典树&#xff0c;又称单词查找树或键树&#xff0c;是一种树形结构&#xff0c;每个节点保存一个字符&#xff0c;一条路径表示一个字符串。它的优点是&#xff1a;利用字符串的公共前缀来减少查询时间&#xff0c;最大限度地减少无谓的字…

Java代码审计安全篇-反序列化漏洞

前言&#xff1a; 堕落了三个月&#xff0c;现在因为被找实习而困扰&#xff0c;着实自己能力不足&#xff0c;从今天开始 每天沉淀一点点 &#xff0c;准备秋招 加油 注意&#xff1a; 本文章参考qax的网络安全java代码审计和部分师傅审计思路以及webgoat靶场&#xff0c;记录…

ASP.NET Mvc+FFmpeg+Video实现视频转码

目录 首先&#xff0c;做了视频上传的页面&#xff1a; FFmpeg&#xff1a;视频转码 FFmpegHelper工作类&#xff1a; 后台控制器代码&#xff1a; 前端视图代码&#xff1a; 参考文章&#xff1a; 首先&#xff0c;做了视频上传的页面&#xff1a; 借鉴了这篇文章 ASP.…

【Miniconda】基于conda列出当前环境下所有已创建的虚拟环境

【Miniconda】基于conda列出当前环境下所有已创建的虚拟环境 &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程&#x1f448; 希望得到您的…

代理IP速度变慢的原因是什么,要如何解决?

许多用户在使用代理IP时都可能会遇到网络速度变慢的问题&#xff0c;这和我们很多人使用代理IP的初衷背道而驰了&#xff0c;所以&#xff0c;代理IP的网络延迟到底是什么原因造成的&#xff0c;我们又要如何解决这个问题呢&#xff1f;今天就和大家一起来探讨探讨。 一、原因 …

C#,图论与图算法,无向图断开点(Articulation Points)的算法与源代码

1 无向图断开点 如果移除无向连通图中的顶点(以及穿过该顶点的边)会断开该图,则该顶点是一个连接点(或切割顶点Cutting Point)。连接点表示连接网络中的漏洞–单点故障会将网络拆分为两个或多个组件。它们对于设计可靠的网络很有用。 对于断开连接的无向图,连接点是顶点…

SSM SpringBoot vue智能手机参数分析平台

SSM SpringBoot vue智能手机参数分析平台 系统功能 首页 图片轮播 新闻资讯 手机信息 手机百科 登录注册 个人中心 后台管理 登录注册 个人中心 手机百科管理 用户管理 手机对比管理 配置管理 新闻资讯管理 手机信息管理 对比信息管理 我的收藏管理 开发环境和技术 开发语言…