1.0.1 • Published 1 year ago

cannon-es-cn v1.0.1

Weekly downloads
-
License
ISC
Repository
-
Last release
1 year ago

这是一个使用 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 插件来创建性能监视器并在场景中显示。

1.0.1

1 year ago

1.0.0

1 year ago