ThreeJs中使用Cannon实现方块自由落体效果

        之前有做过小球的掉落效果,不过那个从画面上只能看出来重力加速度和接触地面反弹的效果,可能没有那么直观,也许用一些js加物理公式也能实现类似的效果,这节用小方块来演示,可以很直观的看出物理世界的现象,因为方块是有棱角的,掉落的时候与地面接触是棱或者角的话就会弹开翻转再落地。        

        同样,我们先设置一个物理世界,在物理世界中放置一个方块和地面,并设置地面和方块之间的反弹恢复系数,同样在Threejs中使用boxGermory设置一个长方体,在渲染的时候保持此长方体和物理世界的小方块保持角度和位置一致,便于在画面上观察小方块的掉落效果。核心代码在下面了,如果自己尝试有问题可以留言向我要完整的源码。

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

      // 新建一个物理小方块:对应threejs的网格小方块
      const boxMaterial = new CANNON.Material()
      this.box = new CANNON.Body({
        mass: 0.3,//碰撞体质量
        material: boxMaterial,//设置小方块的材质
        shape:new CANNON.Box(new CANNON.Vec3(15, 6, 15)),//设置方形大小
      });
      this.box.position.y = 100;//设置小方块的位置
      this.box.quaternion.setFromEuler(Math.PI / 3, Math.PI / 3, Math.PI / 3);
      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, boxMaterial, {
        restitution: 0.2 //反弹恢复系数
      })
      // 把关联的材质添加到物理世界中
      this.world.addContactMaterial(contactMaterial)

      // 实体模型的网格小方块,这里是用来对应显示物理模型下的小方块位置
      const geometry = new THREE.BoxGeometry(15,6, 15);
      const material = new THREE.MeshLambertMaterial({
        color: 0x00ffff,
      });
      this.boxmesh = new THREE.Mesh(geometry, material);
      this.boxmesh.position.y = 100;
      this.boxmesh.rotation.set(Math.PI / 3, Math.PI / 3, Math.PI / 3);
      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)