使用CANNON引擎做物体碰撞
·
一、演示效果
cannon引擎物体碰撞
二、three.js基本步骤
导入,创建场景、相机、渲染器等
三、难点实现
(1)创建一个平面
// 创建平面
const floor = new THREE.Mesh(
new THREE.PlaneGeometry(20, 20),
new THREE.MeshStandardMaterial()
)
floor.receiveShadow = true
floor.position.set(0, -5, 0)
floor.rotation.x = -Math.PI / 2
scene.add(floor)
(2)创建物理世界的平面,并且点击创建立方体
//创建物理世界
const world = new CANNON.World()
world.gravity.set(0, -9.8, 0) //设置物理重力9.8牛
const cubeArr = []
const cancleMaterial = new CANNON.Material('cube')
function createCubeAndBody() {
const cubeGeometry = new THREE.BoxGeometry(1, 1, 1)
const cubeMaterial = new THREE.MeshStandardMaterial()
const cube = new THREE.Mesh(cubeGeometry, cubeMaterial)
cube.castShadow = true
scene.add(cube)
//创建物理立方体形状
const cubeShape = new CANNON.Box(new CANNON.Vec3(0.5, 0.5, 0.5))
//创建物理世界物体
const cubeBody = new CANNON.Body({
shape: cubeShape, //形状
position: new CANNON.Vec3(0, 0, 0),
mass: 1, //质量
material: cancleMaterial,
})
//给物体施加一个 力
cubeBody.applyLocalForce(
new CANNON.Vec3(300, 0, 0), //施加力的大小和方向
new CANNON.Vec3(0, 0, 0) //施加力的位置
)
world.addBody(cubeBody)
const audio = new Audio('/static/click_sound.wav')
//添加监听碰撞事件
function hitEvent(e) {
//碰撞强度
const impactStrength = e.contact.getImpactVelocityAlongNormal()
if (impactStrength > 2) {
audio.currentTime = 0
audio.volume = impactStrength / 12
audio.play()
}
}
cubeBody.addEventListener('collide', hitEvent)
cubeArr.push({
mesh: cube,
body: cubeBody,
})
}
window.addEventListener('click', createCubeAndBody)
四、完整代码
import * as THREE from 'three'
//目标:学习使用cannon引擎
//导入轨道控制器
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
//导入cannon引擎
import * as CANNON from 'cannon-es'
//1、创建场景
const scene = new THREE.Scene()
//2、创建相机
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
) // 参数分别代表,相机角度、屏幕宽高比、近端点,远端点
//设置相机位置
camera.position.set(0, 0, 10)
scene.add(camera)
//创建立方体和平面
const floor = new THREE.Mesh(
new THREE.PlaneGeometry(20, 20),
new THREE.MeshStandardMaterial()
)
floor.receiveShadow = true
floor.position.set(0, -5, 0)
floor.rotation.x = -Math.PI / 2
scene.add(floor)
//添加环境光和平行光
const ambientLight = new THREE.AmbientLight(0xffffff, 1)
const dirLight = new THREE.DirectionalLight(0xffffff, 1)
dirLight.castShadow = true
scene.add(ambientLight)
scene.add(dirLight)
//创建物理世界
const world = new CANNON.World()
world.gravity.set(0, -9.8, 0) //设置物理重力9.8牛
const cubeArr = []
const cancleMaterial = new CANNON.Material('cube')
function createCubeAndBody() {
const cubeGeometry = new THREE.BoxGeometry(1, 1, 1)
const cubeMaterial = new THREE.MeshStandardMaterial()
const cube = new THREE.Mesh(cubeGeometry, cubeMaterial)
cube.castShadow = true
scene.add(cube)
//创建物理立方体形状
const cubeShape = new CANNON.Box(new CANNON.Vec3(0.5, 0.5, 0.5))
//创建物理世界物体
const cubeBody = new CANNON.Body({
shape: cubeShape, //形状
position: new CANNON.Vec3(0, 0, 0),
mass: 1, //质量
material: cancleMaterial,
})
//给物体施加一个 力
cubeBody.applyLocalForce(
new CANNON.Vec3(300, 0, 0), //施加力的大小和方向
new CANNON.Vec3(0, 0, 0) //施加力的位置
)
world.addBody(cubeBody)
const audio = new Audio('/static/click_sound.wav')
//添加监听碰撞事件
function hitEvent(e) {
//碰撞强度
const impactStrength = e.contact.getImpactVelocityAlongNormal()
if (impactStrength > 2) {
audio.currentTime = 0
audio.volume = impactStrength / 12
audio.play()
}
}
cubeBody.addEventListener('collide', hitEvent)
cubeArr.push({
mesh: cube,
body: cubeBody,
})
}
window.addEventListener('click', createCubeAndBody)
//创建物理世界地面
const floorShape = new CANNON.Plane()
const floorMaterial = new CANNON.Material('floor')
const floorBody = new CANNON.Body({
mass: 0, //设置为0表示无论怎么碰撞,位置都不会变
shape: floorShape,
position: new CANNON.Vec3(0, -5, 0),
material: floorMaterial,
})
floorBody.quaternion.setFromAxisAngle(new CANNON.Vec3(1, 0, 0), -Math.PI / 2)
world.addBody(floorBody)
const sphereConcatFloorMaterial = new CANNON.ContactMaterial(
cancleMaterial,
floorMaterial,
{
restitution: 0.7, //弹性
friction: 0.1, //摩擦系数摩擦力
}
)
//将关联材质添加到物理世界中
world.addContactMaterial(sphereConcatFloorMaterial)
//设置默认关联材质,如果不设置,默认使用这个关联材质
world.defaultContactMaterial = sphereConcatFloorMaterial
//初始化渲染器
const renderer = new THREE.WebGLRenderer()
//设置渲染的尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight)
renderer.shadowMap.enabled = true
renderer.physicallyCorrectLights = true
//将webGL渲染的canvas添加到app中
document.getElementById('app').appendChild(renderer.domElement)
//创建控制器
const controls = new OrbitControls(camera, renderer.domElement)
//设置控制器阻尼,让滑动更有真实感
controls.enableDamping = true
//创建坐标轴
const axesHelper = new THREE.AxesHelper(5)
scene.add(axesHelper)
//设置时钟
const clock = new THREE.Clock()
render()
//渲染函数
function render() {
const time = clock.getElapsedTime()
let dateTime = clock.getDelta()
//更新物理引擎
// world.step(1 / 120, dateTime)
world.step(1 / 120)
cubeArr.forEach((item) => {
item.mesh.position.copy(item.body.position)
//设置渲染世界的物体跟随真实世界物体旋转
item.mesh.quaternion.copy(item.body.quaternion)
})
controls.update()
renderer.render(scene, camera)
//下一帧渲染完毕再次执行,保证每一帧都渲染
requestAnimationFrame(render)
}
昇腾计算产业是基于昇腾系列(HUAWEI Ascend)处理器和基础软件构建的全栈 AI计算基础设施、行业应用及服务,https://devpress.csdn.net/organization/setting/general/146749包括昇腾系列处理器、系列硬件、CANN、AI计算框架、应用使能、开发工具链、管理运维工具、行业应用及服务等全产业链
更多推荐

所有评论(0)