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

相关文章
|
机器学习/深度学习 数据采集 人工智能
机器学习实战 | 自动化特征工程工具Featuretools应用
本篇讲解使用自动化特征工程工具Featuretools,对数据进行自动化特征工程的方法,并借助于BigMart Sales数据集来演示自动化特征工程的相关应用。
2561 0
机器学习实战 | 自动化特征工程工具Featuretools应用
|
4月前
|
存储 人工智能 API
AionUi:把 AI 从「聊天框」变成「帮你干活的同事」
AionUi 是一款免费开源的AI协作工作台,内置智能体引擎,零配置、粘贴任意API Key即可使用。支持多智能体协同、远程访问、跨平台及7×24定时自动化,数据本地存储,安全可控。现已上线阿里云计算巢,一键部署,开箱即用。
AionUi:把 AI 从「聊天框」变成「帮你干活的同事」
|
10月前
|
消息中间件 安全 中间件
微服务技术选型:从生态架构视角看go-kratos的不可替代性
本文从生态架构视角解析go-kratos在Go微服务中的不可替代性,剖析其“核心-扩展-应用”三层协同体系,展现其在统一架构、降低集成成本、全场景适配与长期迭代中的综合优势,为技术选型提供深层决策依据。
551 3
|
7月前
|
人工智能 安全 小程序
阿里云怎样部署CoPaw?2026年保姆级攻略来了!
阿里云怎样部署CoPaw?本文将为大家提供一份2026年最新的阿里云部署CoPaw保姆级攻略,零基础也能快速上手,轻松打造专属AI助理!
4535 13
|
算法 安全 定位技术
地图一共有多少个坐标系?有什么区别?如何选择?
地图一共有多少个坐标系?有什么区别?如何选择?
3165 11
|
缓存 算法 网络协议
盘点腾讯后台开发各级工程师(T1-T9)需要具备哪些能力
盘点腾讯后台开发各级工程师(T1-T9)需要具备哪些能力
盘点腾讯后台开发各级工程师(T1-T9)需要具备哪些能力
|
机器学习/深度学习 自然语言处理 搜索推荐
常用的相似度度量总结:余弦相似度,点积,L1,L2
相似性度量在机器学习中起着至关重要的作用。这些度量以数学方式量化对象、数据点或向量之间的相似性。理解向量空间中的相似性概念并采用适当的度量是解决广泛的现实世界问题的基础。本文将介绍几种常用的用来计算两个向量在嵌入空间中的接近程度的相似性度量。
1811 1
|
移动开发 小程序 JavaScript
uView Button 按钮
uView Button 按钮
780 2

热门文章

最新文章