3.js - 物理引擎终极

在这里插入图片描述



import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import gsap from 'gsap' // 导入动画库
import * as dat from 'dat.gui' // 导入dat.gui// 导入 cannon-es 引擎
import * as CANNON from 'cannon-es'// --------------------------------------------------------------------------------const scene = new THREE.Scene()const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 300)
camera.position.set(0, 0, 18)
scene.add(camera)// -------------------------------------------------------------------------------const cubeArr = []
const cubeWorldMaterial = new CANNON.Material('cube')// 创建打击声音
const hitSound = new Audio('../public/assets/metalHit.mp3')const createCube = () => {const cubeGeometry = new THREE.BoxGeometry(1, 1, 1)const cubeMaterial = new THREE.MeshStandardMaterial()const cube = new THREE.Mesh(cubeGeometry, cubeMaterial)cube.castShadow = truescene.add(cube)// 创建物理世界,cube形状const cubeShape = new CANNON.Box(new CANNON.Vec3(0.5, 0.5, 0.5))// 创建物理世界实体const cubeBody = new CANNON.Body({shape: cubeShape,position: new CANNON.Vec3(0, 0, 0),mass: 1, // 质量material: cubeWorldMaterial // 实体材质})cubeBody.applyLocalForce(new CANNON.Vec3(300, 0, 0), // 添加的力的大小和方向new CANNON.Vec3(0, 0, 0) // 施加的力,所在位置)// 将物体,添加到,物理世界world.addBody(cubeBody)// 添加监听碰撞事件const hitEvent = e => {// 获取碰撞强度const impactStrength = e.contact.getImpactVelocityAlongNormal()// console.log('impactStrength=', impactStrength)if (impactStrength > 2) {hitSound.currentTime = 0 // 重新播放hitSound.volume = impactStrength / 12hitSound.play()}}cubeBody.addEventListener('collide', hitEvent)cubeArr.push({mesh: cube,body: cubeBody})
}window.addEventListener('click', createCube)// -------------------------------------------------------------------------------// 创建平面
const floor = new THREE.Mesh(new THREE.PlaneGeometry(20, 20), new THREE.MeshStandardMaterial())
floor.position.set(0, -5, 0)
floor.rotation.x = -Math.PI / 2
floor.receiveShadow = true // 接受别的物体的阴影
scene.add(floor)`创建物理世界`
const world = new CANNON.World()
`设置物理世界的重力,重力被设置为仅在Y轴(竖直向下)上有作用,大小为-9.8(模拟地球表面的重力加速度)`
world.gravity.set(0, -9.8, 0)// 创建 - 物理地面
const floorShape = new CANNON.Plane()
const floorBody = new CANNON.Body()
const floorMaterial = new CANNON.Material('floor')
floorBody.material = floorMaterial`当质量为0时,可以使物体保持不动这里,`floorBody`作为地面,不能动,所以,把它的质量设置为0,就行了 `
floorBody.mass = 0
floorBody.addShape(floorShape)
// 地面的位置
floorBody.position.set(0, -5, 0)
// 旋转地面的位置,围绕X轴(CANNON.Vec3(1, 0, 0))旋转了 -Math.PI / 2(即 90 度)
floorBody.quaternion.setFromAxisAngle(new CANNON.Vec3(1, 0, 0), -Math.PI / 2)
world.addBody(floorBody)`设置,2种材质的碰撞参数`
const defaultContactMaterial = new CANNON.ContactMaterial(cubeWorldMaterial, floorMaterial, {friction: 0.1, `摩擦力`restitution: 0.7 `弹性`
})`将,材料的关联设置,添加到物理世界`
world.addContactMaterial(defaultContactMaterial)`设置,物理世界,碰撞的默认材质,,如果物理世界的物体没有设置这个,就用这个`
world.defaultContactMaterial = defaultContactMaterial// -------------------------------------------------------------------------------// 渲染器透明【渲染器要放在物理世界相关内容后面,不然效果不同】
const renderer = new THREE.WebGLRenderer({ alpha: true })
renderer.setSize(window.innerWidth, window.innerHeight)
renderer.shadowMap.enabled = true
document.body.appendChild(renderer.domElement)// 环境光
const ambientLight = new THREE.AmbientLight(0xffffff, 0.5)
scene.add(ambientLight)
// 平行光
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5)
directionalLight.castShadow = true
directionalLight.position.set(0, 8, 0) // 平行光的位置
scene.add(directionalLight)
// 平行光辅助器
const directionalLightHelp = new THREE.DirectionalLightHelper(directionalLight)
scene.add(directionalLightHelp)
// 创建轨道控制器
const controls = new OrbitControls(camera, renderer.domElement)
controls.enableDamping = true
// 世界坐标辅助器
const axesHelper = new THREE.AxesHelper(5)
scene.add(axesHelper)const clock = new THREE.Clock()const render = () => {// getDelta():返回,距离上次调用,getDelta(),以来经过的秒数let deltaTime = clock.getDelta()/*world.step():更新物理引擎里的世界物体参数一:指定了,物理引擎内部模拟的时间步长(以秒为单位),在这里,设置为,大约每1/120秒更新一次物理世界,参数而:实际的时间差,它允许物理引擎根据实际的帧率调整其模拟,以保持物理行为的稳定性、一致性,*/world.step(1 / 120, deltaTime)// 将物理引擎的sphereBody的位置,复制给渲染引擎的sphere// cube.position.copy(sphereBody.position)cubeArr.forEach(item => {item.mesh.position.copy(item.body.position)// 设置渲染的物体跟随物理的物体旋转item.mesh.quaternion.copy(item.body.quaternion)})renderer.render(scene, camera)requestAnimationFrame(render)
}
render()window.addEventListener('resize', () => {// 重置相机的宽高比camera.aspect = window.innerWidth / window.innerHeight// 更新相机的投影矩阵camera.updateProjectionMatrix()// 重置渲染器的宽高比renderer.setSize(window.innerWidth, window.innerHeight)// 更新渲染器的像素比renderer.setPixelRatio(window.devicePixelRatio)
})

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

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

相关文章

探索GPT-4o mini:开启AI驱动的开发新时代

文章目录 GPT-4o mini:小身材,大能量成本与效能的完美平衡 AI辅助开发:从构想到现实自动化文档编写智能代码审查 提升创新能力:AI驱动的新常态模型驱动的设计思维 社区共享与合作知识共享的重要性 未来展望:AI与人类的…

<数据集>agv仓储机器人识别数据集<目标检测>

数据集格式:VOCYOLO格式 图片数量:1514张 标注数量(xml文件个数):1514 标注数量(txt文件个数):1514 标注类别数:3 标注类别名称:[G1PB2000_Paleteira_AGVS BYD, G1RB5000, AGV-P] 序号类别名称图片数…

6自由度机械手DH坐标系建立

一、建立机械臂DH坐标系 Z为转动关节的转轴,Xi垂直于关节轴i和i1所在的平面,则根据上述方法可以建立坐标系如下图: 二、DH参数表 DH参数设定:机器人的每个连杆可以用4个运动学参数表示,DH法建立坐标系,xi-…

[开端]如何看待“低代码”开发平台的兴起

如何看待“低代码”开发平台的兴起? 近年来,“低代码”开发平台如雨后春笋般涌现,承诺让非专业人士也能快速构建应用程序。这种新兴技术正在挑战传统软件开发模式,引发了IT行业的广泛讨论。低代码平台是提高效率的利器&#xff0…

[开端]JAVA抽象类使用到redis观察着

一、绪论 当redis内容发生变化时需要通知一些观察者做一些动作怎么做? 二、JAVA抽象类 public abstract class AbstractRedisChangeListener {public abstract void change(String key, String value, String crudType); }使用abstract进行修饰一个类 其中抽象类…

SpringBoot中如何自定义自己的过滤器Filter(简易版)

本文不再说SpringMVC中的写法,毕竟现在项目都是SpringBoot,我们还是尽量使用SpringBoot的写法,首先了解一下Filter。 说白了,就是在请求到达服务器之前进行拦截,一般使用场景是拦截登录进行权限校验,当然一…

安装python+python的基础语法

安装python python2为内置,安装python3----3.6.8 最新安装3.12使用源码安装 1.查看yum源,epel [rootpython01 ~]# yum list installed |grep epel 2.安装python3 [rootpython01 ~]# yum -y install python3 3.查看版本 [rootpython01 ~]# python…

Android Studio Gradle多渠道打包

原理使用Android Studio打一次渠道包,用反编译工具反编译后,修改渠道信息重新编译 准备文件 分渠道配置文件:channel.txt ↓ # 多渠道配置里“统计平台”、“市场名称”、“渠道编号”分别代表什么意思? # 统计平台:…

AT32F421驱动BLDC 配合上位机控制与调参

AT32F421驱动BLDC 配合上位机控制与调参 🔧AT32 电机控制与调参上位机软件:ArteryMotorMonitor:https://www.arterytek.com/cn/support/motor_control.jsp?index0🌿测试电机参数:2204-12N14P,无感BLDC&…

LVS(Linux Virtual Server)

简介 LVS(Linux Virtual Server)是一个高性能的开源负载均衡解决方案,它通过在Linux内核中实现IPVS(IP Virtual Server)模块来提供负载均衡功能。LVS能够将外部请求根据特定的算法分发到后端的多个服务器上&#xff0c…

百度文心一言API调用,千帆大模型获取API Key和API Secret图解

百度文心一言大模型调用教程,获取文心一言API Key和API Secret的方法,码笔记mabiji.com告诉大家在百度智能云的千帆大模型平台创建应用,即可获取文心一言的API Key和API Secret,详细流程如下: 1、在百度智能云的千帆大…

gitlab项目添加新成员

gitlab项目添加新成员 1、进入项目,找到settings----->点击Members 2、手动输入要添加成员的账号或者搜索,最后点击Add to project就可以了 choose a role permission 是为要添加的成员选择角色权限 补充: ‌Maintainer:拥…

同态加密和SEAL库的介绍(八)性能

本篇会对比三种加密方案,同时每种方案配置三种参数。即九种情况下的各个操作的性能差异,为大家选择合适的方案和合适的参数提供参考。表格中所有时长的单位均为微妙,即 。 当然数据量比较大,为了方便大家查找&#xff0c…

[BSidesCF 2019]Kookie1

打开题目,看到 根据提示,账号:cookie。密码:monster。试一下登录,登陆成功 抓包看看信息 根据提示, 看一下返回包 账号要加username要改成admin,改一下试试 构造cookie 直接得到flag flag{c…

Redis远程字典服务器(3)——常用数据结构和单线程模型

目录 一,常用数据结构 1.0 前言 1.1 string 1.2 hash 1.3 list 1.4 set 1.5 zset 1.6 演示 二,关于单线程模型 2.1 关于Redis的单线程 2.2 Redis为什么快 一,常用数据结构 1.0 前言 Redis是采用键值对的方式来存储数据的&#…

探索算法系列 - 前缀和算法

目录 一维前缀和(原题链接) 二维前缀和(原题链接) 寻找数组的中心下标(原题链接) 除自身以外数组的乘积(原题链接) 和为 K 的子数组(原题链接) 和可被 …

Java—抽象类和接口 (´▽`)ノ

目录: 一、抽象类: 1、概念: 在面向对象中,所有对象都是由类来创建的,但是呢,并不是所有的类都用来创建类,如果一个类不能描述一个具体的对象,那么这个类就是抽象类。 可以看到,我们…

kotlin简介

Kotlin 是一种在 Java 虚拟机上运行的静态类型编程语言,被称之为 Android 世界的Swift,由 JetBrains 设计开发并开源。 Kotlin 可以编译成Java字节码,也可以编译成 JavaScript,方便在没有 JVM 的设备上运行。 在Google I/O 2017…

嵌入式软件中状态机的几种操作

嵌入式软件中状态机的几种操作 1、状态机的术语 现态:是指当前所处的状态。 条件:又称为“事件”,当一个条件被满足,将会触发一个动作,或者执行一次状态的迁移。 动作:条件满足后执行的动作。动作执行完…

Animate软件基本概念:遮罩层和引导层

这里简单讲一下Animate软件中关于遮罩层和引导层的基本概念。 FlashASer:AdobeAnimate2021软件零基础入门教程https://zhuanlan.zhihu.com/p/633230084 FlashASer:实用的各种Adobe Animate软件教程https://zhuanlan.zhihu.com/p/675680471 FlashASer&…