材质 × 碰撞:Threejs 物理引擎的双重魔法

ops/2025/3/30 17:21:35/

材质

在物理引擎中,材质(Material)用于描述物体的物理属性,例如摩擦力、弹性等。

const material = new CANNON.Material("materialName");

CANNON.Material: 物理材质,用于模拟物体之间的摩擦力、弹性等物理属性。

materialName: 材质的名称,用于标识材质

摩擦

摩擦力是物体在接触时产生的阻力,可以模拟物体之间的摩擦力。

const material = new CANNON.Material("materialName");
material.friction = 0.5;

friction: 摩擦力,取值范围为 0 到 1,值越大,摩擦力越大。

//平面和立方体同样的摩擦系数
const physicsMaterial = new CANNON.Material("physicsMaterial");
//设置摩擦力
physicsMaterial.friction = 0.5;const planeMaterial = new CANNON.Material("planeMaterial");
//设置摩擦力
planeMaterial.friction = 0.5;const planeBody = new CANNON.Body({mass: 0,shape: new CANNON.Plane(),material: planeMaterial,
});const boxBody = new CANNON.Body({mass: 1,shape: new CANNON.Box(new CANNON.Vec3(1, 1, 1)),material: physicsMaterial,
});

在这里插入图片描述

反弹

弹性是物体在碰撞时产生的反弹力,可以模拟物体之间的弹性。

const material = new CANNON.Material("materialName");
material.restitution = 0.5;

restitution: 弹性,取值范围为 0 到 1,值越大,弹性越大。

//平面和立方体同样的弹性系数
const physicsMaterial = new CANNON.Material("physicsMaterial");
//设置弹性
physicsMaterial.restitution = 1;const planeMaterial = new CANNON.Material("planeMaterial");
//设置弹性
planeMaterial.restitution = 1;const planeBody = new CANNON.Body({mass: 0,shape: new CANNON.Plane(),material: planeMaterial,
});const boxBody = new CANNON.Body({mass: 1,shape: new CANNON.Box(new CANNON.Vec3(1, 1, 1)),material: physicsMaterial,
});

在这里插入图片描述

接触材质

接触材质用于描述物体之间的接触属性,例如摩擦力、弹性等。

const physicsMaterial = new CANNON.Material("physicsMaterial");
const planeMaterial = new CANNON.Material("planeMaterial");const contactMaterial = new CANNON.ContactMaterial(physicsMaterial, planeMaterial, {friction: 0.5,restitution: 0.5,
});
world.addContactMaterial(contactMaterial);

ContactMaterial(): 接触材质,用于描述物体之间的接触属性。

  • 第一个参数:第一个物体的材质
  • 第二个参数:第二个物体的材质
  • 第三个参数:一个对象,包含摩擦力、弹性等属性。

world.addContactMaterial(): 将接触材质添加到物理世界中。
在这里插入图片描述

注意: 物体设置的材质效果会优先覆盖接触材质的效果。

碰撞

碰撞是物体在接触时产生的力,可以模拟物体之间的碰撞。

//创建物理立方体
const boxBody = new CANNON.Body({mass: 1,shape: new CANNON.Box(new CANNON.Vec3(0.5, 0.5, 0.5)),position: new CANNON.Vec3(-2, 0.5, 0),material: physicsMaterial,
});
//创建物理球体
const sphereBody = new CANNON.Body({mass: 1,shape: new CANNON.Sphere(0.5),position: new CANNON.Vec3(0, 0.5, 0),material: physicsMaterial,
});
//创建物理圆柱体
const cylinderBody = new CANNON.Body({mass: 1,shape: new CANNON.Cylinder(0.5, 0.5, 1, 32),position: new CANNON.Vec3(2, 0.5, 0),material: physicsMaterial,
});world.add(boxBody);
world.add(sphereBody);
world.add(cylinderBody);//设置立方体初速度
boxBody.velocity.set(2, 0, 0);

CANNON.Box(): 创建一个立方体形状。

CANNON.Sphere(): 创建一个球体形状。

CANNON.Cylinder(): 创建一个圆柱体形状。

velocity: 设置物体的初速度。
在这里插入图片描述

碰撞组

碰撞组用于描述物体之间的碰撞关系,例如物体之间的碰撞是否产生效果。

//设置碰撞组,立方体可以和球体、圆柱体碰撞,球体可以和立方体碰撞,圆柱体可以和立方体碰撞
groundBody.collisionFilterGroup = 1;
boxBody.collisionFilterGroup = 2;
sphereBody.collisionFilterGroup = 4;
cylinderBody.collisionFilterGroup = 8;
groundBody.collisionFilterMask = 2 | 4 | 8;
boxBody.collisionFilterMask = 1 | 4 | 8;
sphereBody.collisionFilterMask = 1 | 2;
cylinderBody.collisionFilterMask = 1 | 2;//第二种写法
const GROUP1 = 1;
const GROUP2 = 2;
const GROUP3 = 4;
const GROUP4 = 8;//地面
const groundBody = new CANNON.Body({mass: 0,shape: new CANNON.Plane(),collisionFilterGroup: GROUP1,collisionFilterMask: GROUP2 | GROUP3 | GROUP4,
});//立方体
const boxBody = new CANNON.Body({mass: 1,shape: new CANNON.Box(new CANNON.Vec3(1, 1, 1)),collisionFilterGroup: GROUP2,collisionFilterMask: GROUP1 | GROUP3 | GROUP4,
});//球体
const sphereBody = new CANNON.Body({mass: 1,shape: new CANNON.Sphere(1),collisionFilterGroup: GROUP3,collisionFilterMask: GROUP1 | GROUP2,
});//圆柱体
const cylinderBody = new CANNON.Body({mass: 1,shape: new CANNON.Cylinder(1, 1, 1, 32),collisionFilterGroup: GROUP4,collisionFilterMask: GROUP1 | GROUP2,
});

collisionFilterGroup: 碰撞组,用于描述物体之间的碰撞关系。

collisionFilterMask: 碰撞掩码,用于描述物体之间的碰撞关系。

注意: 碰撞组与碰撞掩码的值是 2 的幂,可以通过位运算符进行组合。所以这里的四组碰撞组分别是 1、2、4、8。
在这里插入图片描述

碰撞事件

碰撞事件用于描述物体之间的碰撞,例如碰撞时的位置、速度等。

boxBody.addEventListener("collide", (e) => {console.log("碰撞事件", e);console.log("撞击速度", e.contact.getImpactVelocityAlongNormal());
});

addEventListener(): 添加碰撞事件监听器。

  • collide:碰撞事件。

e: 碰撞事件对象。

  • contact:碰撞接触对象。
  • body:碰撞物体对象。
  • target:碰撞目标对象。

getImpactVelocityAlongNormal(): 获取撞击速度。
在这里插入图片描述

书洞笔记


http://www.ppmy.cn/ops/167731.html

相关文章

Redis GeoHash 详解

Redis GeoHash 详解 Redis 提供了 Geo(地理位置) 模块,其中 GeoHash 是一种用于存储和查询地理位置信息的数据结构。它能够高效地进行地理位置存储、查询、计算距离和查找附近地点等操作。 1. 什么是 GeoHash? GeoHash 是一种将…

游戏引擎学习第163天

我们可以在资源处理器中使用库 因为我们的资源处理器并不是游戏的一部分,所以它可以使用库。我说过我不介意让它使用库,而我提到这个的原因是,今天我们确实有一个选择——可以使用库。 生成字体位图的两种方式:求助于 Windows 或…

opengl中的旋转、平移、缩放矩阵生成函数

构建并返回平移矩阵 mat4 buildTranslate(float x, float y, float z) { mat4 trans mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, x, y, z, 1.0 ); return trans; } 构建并返回绕x轴的旋转矩阵 mat4 buildRotateX(float rad) { mat4 xrot mat4(1…

【从零开始学习计算机】计算机网络(二)物理层

【从零开始学习计算机】计算机网络(二)物理层 物理层物理层的四个特性物理层的数据通信物理层关注的问题一,数据同步二,信道的传输速度信道的极限传输速率三,数据编码数字数据编码为模拟信号模拟数据编码为数字信号四,信道复用1,频分复用2,时分复用3,波分复用4,码分多…

基于python+django的家教预约网站-家教信息管理系统源码+运行步骤

该系统是基于pythondjango开发的家教预约网站。是给师妹做的课程作业。大家在学习过程中,遇到问题可以在github给作者留言。共同学习进步哦 效果演示 前台地址: http://jiajiao.gitapp.cn 后台地址: http://jiajiao.gitapp.cn/admin 后台管…

DeepSeek面试——模型架构和主要创新点

本文将介绍DeepSeek的模型架构多头潜在注意力(MLA)技术,混合专家(MoE)架构, 无辅助损失负载均衡技术,多Token 预测(MTP)策略。 一、模型架构 DeepSeek-R1的基本架构沿用…

UE4学习笔记 FPS游戏制作7 敌人的自动寻路

添加一个敌人角色 新建一个蓝图,命名为RobotShooter,为蓝图选择敌人的骨骼mesh 新建一个动画蓝图,命名为RobotShooter_BP,添加一个idle动作,将动作设为Loop,然后为角色蓝图指定这个动画蓝图 将角色蓝图拖入…

【操作系统安全】任务5:Windows 文件与文件系统

目录 一、引言 二、文件系统信息查看 2.1 磁盘与分区信息 2.1.1 diskpart 工具 2.1.2 wmic 查询 2.2 文件系统类型检查 2.3 文件属性查看 2.3.1 dir 命令 2.3.2 attrib 命令 三、文件系统权限配置 3.1 NTFS 权限管理 3.1.1 icacls 命令 3.1.2 特殊权限设置 3.2 所…