Three.js中使用cannon.js实现物理世界

如上图简单生成box,实现自由落体

// 安装cannon
npm i cannon

director.js内容,注:添加地面ground:mass为0;添加box:mass为1

import Template from "../common/Template"
import * as THREE from 'three'
import * as CANNON from 'cannon'
export default class Director extends Template{
  constructor (ele) {
    super()
    this.ele = ele
    this.PCamera.fov = 45
    this.PCamera.far = 10000
    this.PCamera.near = 1
    this.rendererColor = new THREE.Color(0x01031c)
    this.cameraPostion = new THREE.Vector3(300, 200, 0)

    this.init(this.ele)
    this.addLight() 
    this.addAxesHelper(1000)
    if(this.camera && this.renderer) this.addOrbitControls(this.camera, this.renderer.domElement);
    this.animate()

    // 初始化物理世界
    this.world = undefined
    this.initCannon()

    this.addGround()
    this.interval = setInterval(() => {
      this.addBoox()
    }, 2000);
  }
  addBoox(){
    let w = 10;let h = 10;let l = 10
    let height = Math.random()*200
    const geometry = new THREE.BoxBufferGeometry(l,w,h)
    const material = new THREE.MeshLambertMaterial({
      color:0xb99b75
    })
    let box = new THREE.Mesh(geometry, material)
    box.position.set(0,height,0)
    this.scene.add(box)

    let bodyBox = new CANNON.Body({
        mass: 1,
        position: new CANNON.Vec3(0, height, 0),
        shape: new CANNON.Box(new CANNON.Vec3(10,w/2,10)),
        material: new CANNON.Material({friction: 0.1, restitution: 0})
    });//创建一个质量为1kg,位置为(x,20,z),形状为halfSize为1,1,1的正方形刚体,材质中摩擦系数为0.1,弹性系数为0。
    box.userData = bodyBox;//给box的userData属性添加刚体数据
    this.world.addBody(bodyBox);//在物理世界中添加该刚体

    setTimeout(() => { //10秒钟之后在场景中移除box,并在物理世界中移除该刚体
      this.scene.remove(box);
      box.material.dispose();
      box.geometry.dispose();
      this.world.removeBody(bodyBox);
    }, 8000)
  }
  initCannon() {
    this.world = new CANNON.World(); //该方法初始化物理世界,里面包含着物理世界的相关数据(如刚体数据,世界中所受外力等等)
    this.world.gravity.set(0,-9.8,0); //设置物理世界的重力为沿y轴向上-9.8米每二次方秒
    this.world.broadphase = new CANNON.NaiveBroadphase();//NaiveBroadphase是默认的碰撞检测方式,该碰撞检测速度比较高
    this.world.solver.iterations = 5;//解算器的迭代次数,更高的迭代次数意味着更加精确同时性能将会降低
  }
  addGround(){
    const groundGeometry = new THREE.BoxBufferGeometry(300,1,500)
    const groundMaterial = new THREE.MeshLambertMaterial({
      color:0x454942
    })

    let ground = new THREE.Mesh(groundGeometry, groundMaterial)
    ground.rotation.y = -Math.PI/2
    ground.name = '地'
    this.scene.add(ground)
    this.meshList.push(ground)

    let body = new CANNON.Body({
      mass:0,
      position: new CANNON.Vec3(0, 0, 0),
      shape: new CANNON.Box(new CANNON.Vec3(300,1,500)),
      material: new CANNON.Material({friction: 0.05, restitution: 0})
    });//创建一个质量为1kg,位置为(x,20,z),形状为halfSize为1,1,1的正方形刚体,材质中摩擦系数为0.1,弹性系数为0。
    ground.userData = body;//给box的userData属性添加刚体数据
    this.world.addBody(body);//在物理世界中添加该刚体
  }
  addLight(){
    this.addAmbientLight(0x666666)
    this.addDirectionalLight(0xdfebff,{x:50, y:200, z:100},1)
  }
  updatePhysics() { // world.step
    this.world.step(0.1); //第一个参数是以固定步长更新物理世界参数(详情请看api)
    this.scene.children.forEach(d => {//遍历场景中的子对象,如果对象的isMesh属性为true,我们就将更新改对象的position和quaternion属性(他们对应的刚体数据存在对应的userData中)。
        if(d.isMesh == true) {
            d.position.copy(d.userData.position);
            d.quaternion.copy(d.userData.quaternion);
        }
    })
  }
  animate () {
    // 执行运动动画
    if(this.renderer && this.camera){
      this.renderer.render(this.scene, this.camera)
      requestAnimationFrame(this.animate.bind(this))

      this.world?this.updatePhysics():null
    }
  }
}

其他template等文件见 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
要将three.js的模型传递给cannon.js,你需要进行以下步骤: 1. 将three.js的模型转换为cannon.js物理形状。你可以使用Cannon.js自带的几何体工厂来创建物理形状,或者使用第三方库如ThreeToCannonthree.js的模型转换为cannon.js物理形状。 2. 将cannon.js物理形状添加到cannon.js物理世界。你需要创建一个Cannon.World对象,并将物理形状添加到该对象。 3. 在three.js的渲染循环,更新cannon.js物理世界。你需要在每一帧物理世界的物体位置和旋转信息同步到three.js的模型上。 以下是一个简单示例代码,用于将three.js的立方体模型传递给cannon.js,并在物理世界进行模拟: ```javascript // 创建three.js场景和一个立方体模型 const scene = new THREE.Scene(); const cubeGeometry = new THREE.BoxGeometry(1, 1, 1); const cubeMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000 }); const cubeMesh = new THREE.Mesh(cubeGeometry, cubeMaterial); scene.add(cubeMesh); // 将立方体模型转换为cannon.js物理形状 const cubeShape = new CANNON.Box(new CANNON.Vec3(0.5, 0.5, 0.5)); // 创建物理世界和一个刚体对象 const world = new CANNON.World(); const cubeBody = new CANNON.Body({ mass: 1, shape: cubeShape }); world.addBody(cubeBody); // 在渲染循环更新物理世界和模型位置 function render() { requestAnimationFrame(render); // 更新cannon.js物理世界 world.step(1 / 60); // 将物理世界的位置和旋转信息同步到three.js的模型上 cubeMesh.position.copy(cubeBody.position); cubeMesh.quaternion.copy(cubeBody.quaternion); renderer.render(scene, camera); } render(); ``` 注意,这只是一个简单示例,你可能需要根据自己的具体需求进行修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值