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

news/2025/3/22 10:28:21/

材质

在物理引擎中,材质(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/news/1581116.html

相关文章

算法题(103):数独

审题: 本题需要我们找出数独的解,并打印出来 时间复杂度分析: 本题是9*9的数独格子,所以数据量小于25,可以使用2^n的算法 思路: 方法一:深度优先搜索 首先确定搜索及插入策略: 我们采…

[特殊字符] 2025蓝桥杯备赛Day10——B2120 单词的长度

🔍 2025蓝桥杯备赛Day10——B2120 单词的长度 🚀 题目速览 题目难度:⭐️ 适合掌握字符串基本操作 考察重点:字符串分割、空格处理、标点符号处理 B2120 单词的长度 题目描述 输入一行单词序列,相邻单词之间由 …

鸿蒙开发工程师简历项目撰写全攻略

一、项目结构的黄金法则 建议采用「41」结构: 项目背景(业务价值)技术架构(鸿蒙特性)核心实现(技术难点)个人贡献(量化成果)附加价值(延伸影响) …

机器学习算法实战——天气数据分析(主页有源码)

✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连✨ ​ ​​​ 1. 引言 天气数据分析是气象学和数据科学交叉领域的一个重要研究方向。随着大数据技术的发展,气象数据的采集、存储和分…

10-STL、位运算、常用函数库

1-STL vector vector是变长数组 //定义vector vector<int>a;//第一维长233&#xff0c;第二维长度动态变化 vector<int>b[233];//自定义的结构体类型也可以保存在vector中 struct res{...}; vector<rec>c;//函数 a.size();//返回vector的实际长度&#xf…

MacOS下的IntelliJ IDEA突然无法访问本机的虚拟机

今天在开发的过程中&#xff0c;突然遇到一个怪事&#xff0c;之前运行的好好的程序&#xff0c;突然间报无法连接redis服务器&#xff0c;一开始以为是网络问题&#xff0c;在OS的terminal里又是ping 又是telnet的&#xff0c;一切正常&#xff0c;可是程序就是连不上。 挠了半…

车载软件架构 --- AUTOSAR AP/CP中诊断的区别

我是穿拖鞋的汉子&#xff0c;魔都中坚持长期主义的汽车电子工程师。 老规矩&#xff0c;分享一段喜欢的文字&#xff0c;避免自己成为高知识低文化的工程师&#xff1a; 周末洗了一个澡&#xff0c;换了一身衣服&#xff0c;出了门却不知道去哪儿&#xff0c;不知道去找谁&am…

《TCP/IP网络编程》学习笔记 | Chapter 20:Windows 中的线程同步

《TCP/IP网络编程》学习笔记 | Chapter 20&#xff1a;Windows 中的线程同步 《TCP/IP网络编程》学习笔记 | Chapter 20&#xff1a;Windows 中的线程同步用户模式和内核模式用户模式同步内核模式同步 基于 CRITICAL_SECTION 的同步内核模式的同步方法基于互斥量对象的同步基于…