本文目录
- 前言
- 最终复杂模型碰撞效果
- 1、碰撞事件及休眠事件
-
- 1.1 前文回顾及代码整改
- 1.2 效果
- 1.3 监听碰撞事件与休眠
-
- 1.3.1 碰撞事件collide
- 1.3.2 休眠事件sleepy及sleep
- 2、多个形状的组合物体碰撞
-
- 2.1 效果
- 3、Trimesh
-
- 3.1 代码
- 3.2 效果
前言
我们在Cannon-es.js基础入门:3D 物理碰撞效果已经了解了简单的物体碰撞效果,我们还可以监听其碰撞的事件,和监听休眠事件。甚至我们可以实现多个形状的组合物体以及复杂模型的物理碰撞。并且解决了
threejs
里的gltf
模型缩放了7倍,cannon-es
里的Trimesh
该如何对应的问题。
在三维图形与物理模拟的交融领域,cannon-es(一个轻量级、模块化的JavaScript 3D物理引擎库)与three.js(强大的WebGL JavaScript库,用于在网页上创建和显示3D图形)的结合无疑为开发者们提供了一个强大的平台,用于创建既逼真又交互性强的3D场景。本指南将深入探讨如何将这两个库有效结合,实现复杂的物理碰撞检测、物体休眠状态管理以及复杂形状(如Trimesh三角网格)的碰撞处理。
最终复杂模型碰撞效果
1、碰撞事件及休眠事件
1.1 前文回顾及代码整改
我们在Cannon-es.js基础入门:3D 物理碰撞效果的代码基础修改正方体的位置:
box.position.set(-3, 5, 0);
并且增加其物理刚体的材质的弹性属性:
boxMaterial.restitution = 0.7; // 反弹系数
给物理地面材质增加弹性属性:
groundMaterial.restitution = 0.9; // 反弹系数
并且删除其速度的代码
1.2 效果
1.3 监听碰撞事件与休眠
1.3.1 碰撞事件collide
getImpactVelocityAlongNormal
获取碰撞物体速度。
我们监听正方体的碰撞事件,如下代码:
// 碰撞事件
boxBody.addEventListener("collide", (e) => {
console.log('碰撞', e)
let speed = e.contact.getImpactVelocityAlongNormal()
console.log('速度', speed)
})
效果如下:
1.3.2 休眠事件sleepy及sleep
我们首先要先设置物理世界允许休眠:
physicsWorld.allowSleep = true
监听正方体休眠事件及配置:
// 设置立方体允许休眠
boxBody.allowSleep = true
// 设置速度小于1休眠
boxBody.sleepSpeedLimit = 0.5
// 设置1秒后进入休眠
boxBody.sleepTimeLimit = 1
// 监听休眠事件
boxBody.addEventListener("sleepy", (e) => {
console.log('即将进入休眠', e)
})
boxBody.addEventListener("sleep", (e) => {
console.log('已经休眠', e)
})
效果:
2、多个形状的组合物体碰撞
代码如下,创建一个胶囊体:
<template>
<canvas ref="cannonDemo" class="cannonDemo">
</canvas>
</template>
<script setup>
import {
onMounted, ref } from "vue"
import * as THREE from 'three'
import * as CANNON from 'cannon-es'
import {
OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
const cannonDemo = ref('null')
onMounted(() => {
const cannonDemoDomWidth = cannonDemo.value.offsetWidth
const cannonDemoDomHeight = cannonDemo.value.offsetHeight
// 创建场景
const scene = new THREE.Scene
// 创建相机
const camera = new THREE.PerspectiveCamera( // 透视相机
45, // 视角 角度数
cannonDemoDomWidth / cannonDemoDomHeight, // 宽高比 占据屏幕
0.1, // 近平面(相机最近能看到物体)
1000, // 远平面(相机最远能看到物体)
)
camera.position.set(0, 2, 30)
// 创建渲染器
const renderer = new THREE.WebGLRenderer({
antialias: true, // 抗锯齿
canvas: cannonDemo.value
})
// 设置设备像素比
renderer.setPixelRatio(window.devicePixelRatio)
// 设置画布尺寸
renderer.setSize(cannonDemoDomWidth, cannonDemoDomHeight)
// 创建物理世界开始
const physicsWorld = new CANNON.World()
physicsWorld.allowSleep = true
// 设置y轴重力
physicsWorld.gravity.set(0, -9.82, 0)
// 创建物理材料
const groundMaterial = new CANNON.Material('groundMaterial')
groundMaterial.friction = 0.1
groundMaterial.restitution = 1 // 反弹系数
// 设置碰撞组 数值要用2 的幂
const GROUP1 = 1
const GROUP2 = 2
/