cannon-es-cn
v1.0.1
Published
> 这是一个使用 Three.js 和 CANNON.js 物理引擎创建模拟场景的代码。以下是代码解释:
Downloads
2
Readme
这是一个使用 Three.js 和 CANNON.js 物理引擎创建模拟场景的代码。以下是代码解释:
首先,定义了一些变量和物理引擎实例,然后创建了一个名为 MainScene 的异步函数。该函数首先调用了物理引擎实例的 loadGLTF 方法加载了一个 glTF 文件,并在指定位置、旋转和缩放下添加了一个刚体对象。接着,该函数创建了一个平面和两个盒子,并将它们与对应的刚体对象对应起来,以及创建了一个球体并将其与对应的刚体对象对应起来。然后,该函数将物理引擎中的物体的位置信息同步到 Three.js 场景中的模型上。最后,该函数设置了 updateAnimation 函数,在更新动画时将物体的位置信息从物理引擎中同步到 Three.js 场景中的模型上。
接下来,定义了三个用于创建不同形状模型的函数,这些函数根据物理引擎中的刚体对象创建 Three.js 中的 Mesh 对象,并设置了一些材质属性和位置信息。同时,还定义了一个用于同步模型位置信息的函数。
最后,定义了三个事件处理函数:start,stop 和 update。其中,start 函数创建并显示性能监视器,stop 函数移除性能监视器,update 函数则在每个帧上更新物理引擎中的状态,并调用 updateAnimation 函数更新模型的位置信息。
es 加载方式
import * as THREE from 'https://cdn.bootcdn.net/ajax/libs/three.js/0.151.2/three.module.min.js';
import * as CANNON from 'https://unpkg.com/cannon-es/dist/cannon-es.js';
import { PhysicsEngine } from 'https://unpkg.com/cannon-es-cn/src/PhysicsEngine.js';
DEMO 代码
在线预览 https://www.cnbbx.com/360/cannon-es-cn/
// 创建一个初始值为null的stats变量
let stats = null;
// 定义网络模型加载类型
const loader = new GLTFLoader();
const dracoLoader = new DRACOLoader();
dracoLoader.setDecoderPath(
"https://unpkg.com/three/examples/jsm/libs/draco/gltf/"
);
loader.setDRACOLoader(dracoLoader);
// 创建物理引擎实例并开启调试模式
const physicsEngine = new PhysicsEngine(scene);
physicsEngine.debug(true);
// 创建updateAnimation函数并初始化为null
let updateAnimation = null;
// 定义MainScene异步函数
const MainScene = async () => {
// 加载一个glTF文件并在指定位置、旋转和缩放下添加刚体对象
await physicsEngine.loadGLTF(loader, '冰墩墩.glb', new CANNON.Vec3(-1, 2, 0), new CANNON.Quaternion(), 3, 5, 50, 0, "BOX").then((res) => { });
// 创建平面和两个盒子
const planeBody = physicsEngine.addPlane(
new CANNON.Vec3(0, 0, 0),
new CANNON.Quaternion().setFromEuler(-Math.PI / 2, 0, 0)
);
const box1Body = physicsEngine.addBox(
[0.5, 0.5, 0.5],
new CANNON.Vec3(0, 10, 0),
new CANNON.Quaternion(),
1
);
const box2Body = physicsEngine.addBox(
[0.5, 0.5, 0.5],
new CANNON.Vec3(2, 10, 0),
new CANNON.Quaternion(),
1
);
// 将Three.js场景中的平面、盒子模型与CANNON.js物理引擎中的刚体对象对应
const planeMesh = createPlaneMesh(planeBody);
const box1Mesh = createBoxMesh(box1Body);
const box2Mesh = createBoxMesh(box2Body);
scene.add(planeMesh);
scene.add(box1Mesh);
scene.add(box2Mesh);
// 创建一个球体并将其与CANNON.js物理引擎中的刚体对象对应
const sphereBody = physicsEngine.addSphere(
0.5,
new CANNON.Vec3(-2, 50, 0),
new CANNON.Quaternion(),
1,
0.3,
0
);
// 将Three.js场景中的球体模型与CANNON.js物理引擎中的刚体对象对应
const sphereMesh = createSphereMesh(sphereBody);
scene.add(sphereMesh);
// 设置updateAnimation函数,在更新动画时将模型位置信息从物理引擎中同步到Three.js场景中
updateAnimation = () => {
updateMeshPosition(box1Body, box1Mesh);
updateMeshPosition(box2Body, box2Mesh);
updateMeshPosition(sphereBody, sphereMesh);
}
}
// 调用MainScene函数
MainScene();
// 创建一个用于创建平面模型的函数,并将其位置和旋转信息从物理引擎中同步到Three.js场景中
function createPlaneMesh(planeBody) {
const planeGeometry = new THREE.PlaneGeometry(100, 100);
const planeMaterial = new THREE.MeshStandardMaterial({
color: "#ffffff",
side: THREE.DoubleSide,
});
const planeMesh = new THREE.Mesh(planeGeometry, planeMaterial);
planeMesh.position.set(planeBody.position.x, planeBody.position.y, planeBody.position.z);
planeMesh.quaternion.copy(planeBody.quaternion);
planeMesh.receiveShadow = true;
return planeMesh;
}
// 创建一个用于创建盒子模型的函数,并将其位置和旋转信息从物理引擎中同步到Three.js场景中
function createBoxMesh(boxBody) {
const boxGeometry = new THREE.BoxGeometry(...boxBody.shapes[0].halfExtents.scale(2).toArray());
const boxMaterial = new THREE.MeshStandardMaterial({
color: "#ff0000",
});
const boxMesh = new THREE.Mesh(boxGeometry, boxMaterial);
boxMesh.position.set(boxBody.position.x, boxBody.position.y, boxBody.position.z);
boxMesh.quaternion.copy(boxBody.quaternion);
boxMesh.castShadow = true;
boxMesh.receiveShadow = true;
return boxMesh;
}
// 创建一个用于创建球体模型的函数,并将其位置和旋转信息从物理引擎中同步到Three.js场景中
function createSphereMesh(sphereBody) {
const sphereGeometry = new THREE.SphereGeometry(sphereBody.shapes[0].radius, 32, 32);
const sphereMaterial = new THREE.MeshPhysicalMaterial({
color: "#0000ff",
metalness: 1,
roughness: 0,
clearcoat: 1,
transmission: 0.9,
transparent: true,
opacity: 0.8,
});
const sphereMesh = new THREE.Mesh(sphereGeometry, sphereMaterial);
sphereMesh.position.set(sphereBody.position.x, sphereBody.position.y, sphereBody.position.z);
sphereMesh.quaternion.copy(sphereBody.quaternion);
sphereMesh.castShadow = true;
sphereMesh.receiveShadow = true;
return sphereMesh;
}
// 将模型位置与物理引擎中的刚体同步
function updateMeshPosition(body, mesh) {
mesh.position.copy(body.position);
mesh.quaternion.copy(body.quaternion);
}
// 定义update事件处理函数,更新物理引擎状态并调用updateAnimation函数
function update(event) {
physicsEngine.update();
if (updateAnimation) updateAnimation.call(this);
if (stats) stats.update(); // 更新性能监视器
}
// 定义start事件处理函数,创建并显示性能监视器
function start(event) {
stats = new Stats();
document.body.appendChild(stats.dom);
}
// 定义stop事件处理函数,移除性能监视器
function stop(event) {
if (stats) stats.dom.remove();
}
以上代码使用了 Three.js 和 CANNON.js 的 API 来创建物理模拟场景,并将模型位置信息从物理引擎中同步到 Three.js 场景中。同时,还使用了 Stats.js 插件来创建性能监视器并在场景中显示。