Three.js物理引擎与物体的相互作用——物体碰撞地面、碰撞事件、碰撞音效

part

导入3D引擎库 

import * as CANNON from "cannon-es"

 创建three.js中物体与地面

// 创建球体
const spereGeometry = new THREE.SphereGeometry(1, 20, 20)
const spereMaterial = new THREE.MeshStandardMaterial()
const sphere = new THREE.Mesh(spereGeometry, spereMaterial)
sphere.castShadow = true
scene.add(sphere)

// 创建平面
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 ambientLight = new THREE.AmbientLight(0xffffff, 0.5)
scene.add(ambientLight)
const dirLight = new THREE.DirectionalLight(0xffffff, 0.5)
dirLight.castShadow = true
scene.add(dirLight)

仅仅通过three中的物体实现物理效果是无法实现的

需要借助 CANNON 创建物理世界的小球

  • 需要注意:想要页面中物体具有物理世界的效果(有重力,有碰撞效果),那么就必须在物理世界再创造一个物体
  • 普通小球是在:渲染引擎进行渲染,引擎只负责不断的画画,绘制出它该有的样子
  • 物理世界小球是在:物理引擎就行计算其该有的物理效果,渲染引擎不断的从物理引擎中获取小球物理数据,然后进行绘制
  • 设置完物理世界的物体后,记得将两个世界的小球进行关联,将真实世界小球位置坐标赋给所看到(普通小球)的小球坐标,详情下面render函数
const world = new CANNON.World() // 创建物理世界
world.gravity.set(0, -9.8, 0) // 设置世界重力,y向下为负,真实世界重力加速度为9.8NM
const sphereShape = new CANNON.Sphere(1) // 半径为1的小球形状
// 设置物体材质
const sphereWorldMaterial = new CANNON.Material()
// 创建物理世界的物体,类似于假世界的 Mesh步骤
const sphereBody = new CANNON.Body({
    shape: sphereShape,
    position: new CANNON.Vec3(0, 0, 0),
    mass: 1, // 小球质量 (相互碰撞会有什么效果)
    material: sphereWorldMaterial, // 材质

})
// 将物体添加到物理世界
world.addBody(sphereBody)

 render渲染函数中对物体位置信息赋值

const render = () => {
    // 更新物理引擎世界的物体
    world.step(1 / 120, 0.02) // 每帧渲染120次 

    // 将物理世界小球位置坐标赋值给普通小球
    sphere.position.copy(sphereBody.position)

    controls.update()
    renderer.render(scene, camera)
    requestAnimationFrame(render) // 请求动画会给render传递一个时间,为当前请求动画帧执行的毫秒数
}
render()

监听物理小球碰撞事件 collide,加入碰撞音效

const hitSound = new Audio(require('../assets/audio/yes.mp3'))     
function HitEvent(e) {
    console.log(e);
    const impactStrength = e.contact.getImpactVelocityAlongNormal() // 获取碰撞的强度
    console.log(impactStrength); // 两次碰撞,第一次8.1, 第二次1.1
    hitSound.play() // 碰撞时播放声音
}
sphereBody.addEventListener('collide', HitEvent) // 碰撞反弹了几下,就会执行几下

第一次碰撞力度8.8..Nm, 第二次碰撞力度1.8..Nm

  • body 要碰撞的物体
  • target 要被碰撞的物体
  • contect 碰撞的信息,包含坐标,力度,时间等信息 

猜你喜欢

转载自blog.csdn.net/dabaooooq/article/details/130433263