Appearance
物理系统
安装cannon依赖
npm install --save cannon-es
使用逻辑:
1、导入
import * as CANNON from 'cannon-es'
可以取符合命名规则的,自己喜欢的名字
2、创建物理世界,创建物体,添加到世界
javascript
// 创建物理世界
const world = new CANNON.World();
world.gravity.set(0, -9.8, 0);
// 设置物体材质
const sphereWorldMaterial = new CANNON.Material();
// 创建物理小球
const sphereShape = new CANNON.Sphere(1);
const sphereBody = new CANNON.Body({
shape: sphereShape,
position: new CANNON.Vec3(0,5,0),
mass: 1,
material: sphereWorldMaterial,
});
// 将物体添加到物理世界
world.addBody(sphereBody);
// 渲染里渲染物理世界
const clock = new THREE.Clock();
function animate() {
controls.update();
// 下面这两行
world.step(1/120, clock.getDelta());
sphere.position.copy(sphereBody.position);
requestAnimationFrame( animate );
renderer.render( scene, camera );
}
3、代码示例:
javascript
import * as CANNON from 'cannon-es';
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
// 1、创建场景
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 sphereGeometry = new THREE.SphereGeometry(1, 20, 20);
const sphereMaterial = new THREE.MeshStandardMaterial();
const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
sphere.castShadow = true;
scene.add(sphere);
const floor = new THREE.Mesh(
new THREE.PlaneGeometry(10, 10),
new THREE.MeshStandardMaterial()
);
floor.position.set(0, -1, 0);
floor.rotation.x = -Math.PI / 2;
floor.receiveShadow = true;
scene.add(floor);
// 创建物理世界
const world = new CANNON.World();
world.gravity.set(0, -9.8, 0);
// 设置物体材质
const sphereWorldMaterial = new CANNON.Material();
// 创建物理小球
const sphereShape = new CANNON.Sphere(1);
const sphereBody = new CANNON.Body({
shape: sphereShape,
position: new CANNON.Vec3(0,5,0),
mass: 1,
material: sphereWorldMaterial,
});
// 创建物理地面
const floorShape = new CANNON.Plane();
const floorBody = new CANNON.Body({
shape: floorShape,
position: new CANNON.Vec3(0, -1, 0),
mass: 0,
});
floorBody.quaternion.setFromAxisAngle(new CANNON.Vec3(1, 0, 0), -Math.PI/2);
// 将物体添加到物理世界
world.addBody(sphereBody);
world.addBody(floorBody);
// 添加环境光、平行光
const ambientLight = new THREE.AmbientLight(0xffffff, 1.0);
const dirLight = new THREE.DirectionalLight(0xffffff, 1.0);
dirLight.castShadow = true;
scene.add(ambientLight);
scene.add(dirLight);
// 初始化渲染器
const renderer = new THREE.WebGLRenderer();
// 设置渲染的尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight);
// console.log(renderer);
// 将webgl渲染的canvas内容添加到body
document.body.appendChild(renderer.domElement);
const controls = new OrbitControls(camera, renderer.domElement);
// 使用渲染器,通过相机将场景渲染进来
renderer.render(scene, camera);
const clock = new THREE.Clock();
const axesHelper = new THREE.AxesHelper(5);
scene.add(axesHelper);
function animate() {
controls.update();
world.step(1/120, clock.getDelta());
sphere.position.copy(sphereBody.position);
requestAnimationFrame( animate );
renderer.render( scene, camera );
}
animate();
window.addEventListener("resize", () => {
// 更新宽高比
camera.aspect = window.innerWidth / window.innerHeight;
// 更新摄像机的投影矩阵
camera.updateProjectionMatrix();
// 更新渲染器
renderer.setSize(window.innerWidth, window.innerHeight);
// 设置渲染器的像素比
renderer.setPixelRatio(window.devicePixelRatio);
});
window.addEventListener("dblclick", () => {
const isFull = document.fullscreenElement;
if(!isFull){
renderer.domElement.requestFullscreen();
isFull = true;
}
document.exitFullscreen();
});
监听碰撞
javascript
function HitEvent(e){
console.log(e);
}
sphereBody.addEventListener("collide", HitEvent);
- 获取碰撞强度
getImpactVelocityAlongNormal()
javascript
function HitEvent(e){
const impactStrength = e.contact.getImpactVelocityAlongNormal();
console.log(impactStrength);
}
设置物理材质
javascript
const sphereWorldMaterial = new CANNON.Material("default");
const defaultContactMaterial = new CANNON.ContactMaterial(
sphereMaterial,
{
friction: 0.1, // 摩擦力
restitution: 0.7 // 弹性
}
)
// 将材料的关联设置添加到物理世界
world.addContactMaterial(defaultContactMaterial);
添加互相间的碰撞
施加力
applyLocalForce()
javascript
cubeBody.applyLocalForce(
new CANNON.Vec3(18, 0, 0), // 力的大小和方向
new CANNON.Vec3(0, 0, 0) // 施加的力的位置
);