ThreeJs实现小球自由落体效果

简介: 这篇文章详细介绍了如何在Three.js中利用物理引擎Cannon.js实现小球自由落体效果,包括物理世界的创建、物体的添加及同步物理状态到三维场景中的具体实现。

之前有做过关于Threejs基础功能的一些演示,包括绘制简单的模型,以及给这个模型添加一些动画,但是这些都还是停留在绘制的阶段,动画也是匀速移动,而非模仿自然界中的重力加速度以及阻力等效果实现的。

今天讲一个可以模拟自然界中一些物理属性的组件,这里引入一个新的组件Cannon,这是一个开源3D物理引擎,可以用来开发和模拟真实世界的物理效果,包括碰撞,重力,约束等,

Cannon.js的特点如下:

轻量级和高性能:Cannon.js被设计为一个快速而轻便的物理引擎,代码简洁且易于理解。 真实的物理模拟:Cannon.js提供了一套完整的3D物理模拟功能,包括刚体碰撞、力学模拟和约束等。这使得开发者可以模拟真实世界中的物理效果。 灵活的约束系统:Cannon.js的约束系统非常灵活,并且支持各种类型的约束,如距离约束、弹簧约束、旋转约束等。开发者可以根据需要创建各种类型的约束。 基于WebGL:Cannon.js与WebGL技术结合使用,可以轻松实现在浏览器中展示3D物理效果,并且与其他WebGL应用程序进行集成。 跨平台兼容性:Cannon.js可以在多种浏览器上运行,并且支持移动设备和桌面设备。这使得开发者可以轻松地在各种平台上开发和运行物理模拟应用程序。 下面来制作一个通过cannon来制作的一个自由落体的效果,因为传统threejs,即使做成动画效果一般也只是匀速移动,很难做出下落时有重力加速度的效果,首先还是需要用threejs绘制一个场景,在场景中去添加cannon的一些属性和方法,主要流程如下,先创建一个物理世界,在物理世界中添加一个球体和一个底面,让球落到底面,但是因为cannon中不提供具体的模型显示,所以我们需要根据物理模型来构建实体模型,并同步物理模型中的球体位置到实体模型中的物体位置。

按照threejs的步骤搭建一个3D场景,下面在物理场景中添加一个地面以及一个球体:

// 实体模型的网格小球,这里是用来对应显示物理模型下的球体位置
      const geometry = new THREE.SphereGeometry(3);
      const material = new THREE.MeshLambertMaterial({
        color: 0x00ffff,
      });
      this.boxmesh = new THREE.Mesh(geometry, material);
      this.scene.add(this.boxmesh)

      //实体地面的网格模型,这里用来显示对应物理对应的地面
      const planeGeometry = new THREE.PlaneGeometry(200, 200);
      const planeMaterial = new THREE.MeshLambertMaterial({
        color:0x777777,
      });
      const planeMesh = new THREE.Mesh(planeGeometry, planeMaterial);
      planeMesh.rotateX(-Math.PI / 2);
      this.scene.add(planeMesh)

效果如下

ThreeJs实现小球自由落体效果_实体模型

下面要给这个小球添加物理属性,比如重力加速度以及落地后根据材质的不同设置回弹的系数,物理属性实际上是配置另一套物理模型,新建物理世界,在物理世界中创建小球模型和地面模型,然后将threejs中我们绘制的模型与物理世界的模型绑定起来,当物理世界的球体位置发生变化的时候,threejs场景中球体位置也随着发生变化,那么就等于是吧物理引擎的一套规则投射到threejs场景中了,下面就需要创建一套物理世界的规则:

//新建一个物理模型世界
      this.world = new CANNON.World();
      // 设置物理世界重力加速度,此处设置为y轴的反方向,也就是往y轴反方向存在重力
      this.world.gravity.set(0, -9.8, 0);

      // 新建一个物理小球:对应threejs的网格小球
      const sphereMaterial = new CANNON.Material()
      this.box = new CANNON.Body({
        mass: 1,//碰撞体质量
        material: sphereMaterial,//设置小球的材质
        shape:new CANNON.Sphere(3),//设置小球的半径大小
      });
      this.box.position.y = 100;//设置小球的位置
      this.world.addBody(this.box);//将小球添加到物理世界中

      // 新建物理地面
      const groundMaterial = new CANNON.Material()
      const groundBody = new CANNON.Body({
        mass: 0, // 质量为0,始终保持静止,不会受到力碰撞或加速度影响
        shape:new CANNON.Plane(),//新建物理模型的底面
        material: groundMaterial,//地面材质
      });
      // 改变平面默认的方向,法线默认沿着z轴,旋转到平面向上朝着y方向
      groundBody.quaternion.setFromEuler(-Math.PI / 2, 0, 0);
      this.world.addBody(groundBody);

创建完成后为了动态效果还需要再渲染中刷新页面:

initAnimate() {
      requestAnimationFrame(this.initAnimate);
      this.world.step(1/60);
      // 渲染循环中,同步物理球body与网格球mesh的位置
      this.boxmesh.position.copy(this.box.position);
      this.renderer.render(this.scene, this.camera);
    },

最终的完整代码如下:

initCarton(){
      //新建一个物理模型世界
      this.world = new CANNON.World();
      // 设置物理世界重力加速度,此处设置为y轴的反方向,也就是往y轴反方向存在重力
      this.world.gravity.set(0, -9.8, 0);

      // 新建一个物理小球:对应threejs的网格小球
      const sphereMaterial = new CANNON.Material()
      this.box = new CANNON.Body({
        mass: 1,//碰撞体质量
        material: sphereMaterial,//设置小球的材质
        shape:new CANNON.Sphere(3),//设置小球的半径大小
      });
      this.box.position.y = 100;//设置小球的位置
      this.world.addBody(this.box);//将小球添加到物理世界中

      // 新建物理地面
      const groundMaterial = new CANNON.Material()
      const groundBody = new CANNON.Body({
        mass: 0, // 质量为0,始终保持静止,不会受到力碰撞或加速度影响
        shape:new CANNON.Plane(),//新建物理模型的底面
        material: groundMaterial,//地面材质
      });
      // 改变平面默认的方向,法线默认沿着z轴,旋转到平面向上朝着y方向
      groundBody.quaternion.setFromEuler(-Math.PI / 2, 0, 0);
      this.world.addBody(groundBody);

      // 设置地面材质和小球材质之间的碰撞反弹恢复系数,也就是底面和小球的材质之间存在的反弹系数,
      const contactMaterial = new CANNON.ContactMaterial(groundMaterial, sphereMaterial, {
        restitution: 0.5 //反弹恢复系数
      })
      // 把关联的材质添加到物理世界中
      this.world.addContactMaterial(contactMaterial)

      // 实体模型的网格小球,这里是用来对应显示物理模型下的球体位置
      const geometry = new THREE.SphereGeometry(3);
      const material = new THREE.MeshLambertMaterial({
        color: 0x00ffff,
      });
      this.boxmesh = new THREE.Mesh(geometry, material);
      this.scene.add(this.boxmesh)

      //实体地面的网格模型,这里用来显示对应物理对应的地面
      const planeGeometry = new THREE.PlaneGeometry(200, 200);
      const planeMaterial = new THREE.MeshLambertMaterial({
        color:0x777777,
      });
      const planeMesh = new THREE.Mesh(planeGeometry, planeMaterial);
      planeMesh.rotateX(-Math.PI / 2);
      this.scene.add(planeMesh)
    },

    initAnimate() {
      requestAnimationFrame(this.initAnimate);
      this.world.step(1/60);
      // 渲染循环中,同步物理球body与网格球mesh的位置
      this.boxmesh.position.copy(this.box.position);
      this.renderer.render(this.scene, this.camera);
    },

实现效果如下:

这里不支持上传视频,我就只能上传个图片了,如果想看动态效果可以私我,我发给你视频,或者需要源码也可以给我私信:

ThreeJs实现小球自由落体效果_实体模型_02

相关文章
|
24天前
|
弹性计算 人工智能 架构师
阿里云携手Altair共拓云上工业仿真新机遇
2024年9月12日,「2024 Altair 技术大会杭州站」成功召开,阿里云弹性计算产品运营与生态负责人何川,与Altair中国技术总监赵阳在会上联合发布了最新的“云上CAE一体机”。
阿里云携手Altair共拓云上工业仿真新机遇
|
16天前
|
存储 关系型数据库 分布式数据库
GraphRAG:基于PolarDB+通义千问+LangChain的知识图谱+大模型最佳实践
本文介绍了如何使用PolarDB、通义千问和LangChain搭建GraphRAG系统,结合知识图谱和向量检索提升问答质量。通过实例展示了单独使用向量检索和图检索的局限性,并通过图+向量联合搜索增强了问答准确性。PolarDB支持AGE图引擎和pgvector插件,实现图数据和向量数据的统一存储与检索,提升了RAG系统的性能和效果。
|
4天前
|
JSON 自然语言处理 数据管理
阿里云百炼产品月刊【2024年9月】
阿里云百炼产品月刊【2024年9月】,涵盖本月产品和功能发布、活动,应用实践等内容,帮助您快速了解阿里云百炼产品的最新动态。
阿里云百炼产品月刊【2024年9月】
|
1天前
|
人工智能 Rust Java
10月更文挑战赛火热启动,坚持热爱坚持创作!
开发者社区10月更文挑战,寻找热爱技术内容创作的你,欢迎来创作!
202 11
|
19天前
|
人工智能 IDE 程序员
期盼已久!通义灵码 AI 程序员开启邀测,全流程开发仅用几分钟
在云栖大会上,阿里云云原生应用平台负责人丁宇宣布,「通义灵码」完成全面升级,并正式发布 AI 程序员。
|
21天前
|
机器学习/深度学习 算法 大数据
【BetterBench博士】2024 “华为杯”第二十一届中国研究生数学建模竞赛 选题分析
2024“华为杯”数学建模竞赛,对ABCDEF每个题进行详细的分析,涵盖风电场功率优化、WLAN网络吞吐量、磁性元件损耗建模、地理环境问题、高速公路应急车道启用和X射线脉冲星建模等多领域问题,解析了问题类型、专业和技能的需要。
2578 22
【BetterBench博士】2024 “华为杯”第二十一届中国研究生数学建模竞赛 选题分析
|
3天前
|
存储 人工智能 搜索推荐
数据治理,是时候打破刻板印象了
瓴羊智能数据建设与治理产品Datapin全面升级,可演进扩展的数据架构体系为企业数据治理预留发展空间,推出敏捷版用以解决企业数据量不大但需构建数据的场景问题,基于大模型打造的DataAgent更是为企业用好数据资产提供了便利。
165 2
|
1天前
|
编译器 C#
C#多态概述:通过继承实现的不同对象调用相同的方法,表现出不同的行为
C#多态概述:通过继承实现的不同对象调用相同的方法,表现出不同的行为
100 65
|
20天前
|
机器学习/深度学习 算法 数据可视化
【BetterBench博士】2024年中国研究生数学建模竞赛 C题:数据驱动下磁性元件的磁芯损耗建模 问题分析、数学模型、python 代码
2024年中国研究生数学建模竞赛C题聚焦磁性元件磁芯损耗建模。题目背景介绍了电能变换技术的发展与应用,强调磁性元件在功率变换器中的重要性。磁芯损耗受多种因素影响,现有模型难以精确预测。题目要求通过数据分析建立高精度磁芯损耗模型。具体任务包括励磁波形分类、修正斯坦麦茨方程、分析影响因素、构建预测模型及优化设计条件。涉及数据预处理、特征提取、机器学习及优化算法等技术。适合电气、材料、计算机等多个专业学生参与。
1578 16
【BetterBench博士】2024年中国研究生数学建模竞赛 C题:数据驱动下磁性元件的磁芯损耗建模 问题分析、数学模型、python 代码
|
4天前
|
Linux 虚拟化 开发者
一键将CentOs的yum源更换为国内阿里yum源
一键将CentOs的yum源更换为国内阿里yum源
240 2