three.js cannon.js物理引擎之约束(二)
今天郭先生继续讲cannon.js的物理约束,之前的一篇文章曾简单的提及过PointToPointConstraint约束,那么今天详细的说一说cannon.js的约束和使用方法。在线案例请点击博客原文。
1. cannon.js约束的种类
1. PointToPointConstraint点对点约束
它的构造函数如下(之前可能介绍过了,这次统一说)
PointToPointConstraint ( bodyA pivotA bodyB pivotB maxForce )
- bodyA — 刚体A。
- pivotA — 相对于刚体A的质心的点,刚体A被约束到该点。
- bodyB — 刚体B。
- pivotB — 相对于刚体B的质心的点,刚体B被约束到该点。
- maxForce — 约束物体应施加的最大力。
点对点约束顾名思义就是A刚体的某一点和B刚体的某一点形成约束,刚体之间仅通过约束点相连,如下图。

2. LockConstraint锁定约束
它的构造函数如下
LockConstraint ( bodyA bodyB { maxForce } )
- bodyA — 刚体A。
- bodyB — 刚体B。
- maxForce — 约束物体应施加的最大力。
为什么不需要设置约束点的位置呢,因为锁定约束其实就是点对点约束的简化版本,他们pivotA和pivotB默认为刚体的中心,如下图。

3. DistanceConstraint距离约束
它的构造函数如下
DistanceConstraint ( bodyA bodyB distance maxForce )
- bodyA — 刚体A。
- bodyB — 刚体B。
- distance — 要保持的距离。如果未定义,它将被设置为刚体A和刚体B之间的当前距离。
- maxForce — 约束物体应施加的最大力。
距离约束将两个物体约束为彼此重心的距离恒定,如下图是相邻小球保持恒定距离。

4. HingeConstraint铰链约束
它的构造函数如下
HingeConstraint ( bodyA bodyB { pivotA axisA pivotB axisB maxForce } )
- bodyA — 刚体A。
- bodyB — 刚体B。
- pivotA — 相对于刚体A的质心的点,刚体A被约束到该点。
- axisA — 在刚体A中局部定义的刚体A可以绕其旋转的轴。
- pivotB — 相对于刚体B的质心的点,刚体B被约束到该点。
- axisB — 在刚体B中局部定义的刚体B可以绕其旋转的轴。
- maxForce — 约束物体应施加的最大力。
铰链又称合页,这个约束就像门的铰链一样,让两个物理只能在各自的点沿着固定的轴旋转。如下图。

2. 案例的主要代码
下面是案例的主要代码
var bodies = [], meshes = [];
initPoint() {
var size = 0.5;
var boxShape = new CANNON.Box(new CANNON.Vec3(size,size,size));
var mass = 0;
var N=10, last;
for(var i=0; i<N; i++){
// Create a box
var boxbody = new CANNON.Body({
mass: mass,
shape: boxShape,
position: new CANNON.Vec3(i * 0.6, (N - i) * Math.sqrt(size * size * 3) * 2, 0),
quaternion: new CANNON.Quaternion().setFromEuler(-Math.PI / 4, -Math.PI / 4, 0),
material: pubMaterial
});
boxbody.angularDamping = 0.3;
bodies.push(boxbody);
world.addBody(boxbody);
if(i == 0) {
mass = 1;
} else {
var c = new CANNON.PointToPointConstraint(boxbody, new CANNON.Vec3(size, size ,size), last, new CANNON.Vec3(-size, -size ,-size));
world.addConstraint(c);
}
last = boxbody;
}
for(let i=0; i<10; i++) {
let mesh = new THREE.Mesh(new THREE.BoxBufferGeometry(1), new THREE.MeshNormalMaterial());
meshes.push(mesh);
scene.add(mesh);
}
console.log(world)
}
initLock() {
var size = 0.5;
var boxShape = new CANNON.Box(new CANNON.Vec3(size,size,size));
var mass = 1;
var space = 0.1*size;
var N=10, last;
for(var i=0; i<N; i++){
// Create a box
var boxbody = new CANNON.Body({
mass: mass,
shape: boxShape,
position: new CANNON.Vec3((N-i-N/2)*(size*2+2*space), size*6+space, 0),
sleepSpeedLimit: 0,
material: pubMaterial
});
bodies.push(boxbody);
world.addBody(boxbody);
if(last){
// Connect the current body to the last one
var c = new CANNON.LockConstraint(boxbody, last);
world.addConstraint(c);
}
// To keep track of which body was added last
last = boxbody;
}
var bodyA = new CANNON.Body({
mass: 0,
shape: boxShape,
position: new CANNON.Vec3((-N/2+1)*(size*2+2*space), size*3-1, 0),
material: pubMaterial
});
bodies.push(bodyA);
world.addBody(bodyA);
var bodyB = new CANNON.Body({
mass: 0,
shape: boxShape,
position: new CANNON.Vec3((N/2)*(size*2+2*space), size*3-1, 0),
material: pubMaterial
});
bodies.push(bodyB);
world.addBody(bodyB);
for(let i=0; i<12; i++) {
let mesh = new THREE.Mesh(new THREE.BoxBufferGeometry(1), new THREE.MeshNormalMaterial());
meshes.push(mesh);
scene.add(mesh);
}
}
initCloth() {
var size = 0.2;
var dis = 0.5;
var sphereShape = new CANNON.Sphere(size);
var mass = 1;
var Nrows = 15, Ncols = 15;
for(let i=0; i<Nrows; i++) {
for(let j=0; j<Ncols; j++) {
let body = new CANNON.Body({
mass: mass,
shape: sphereShape,
position: new CANNON.Vec3((i - 0.5 * Nrows + 0.5) * dis, 9, (j - 0.5 * Ncols + 0.5) * dis),
material: pubMaterial
})
bodies.push(body);
world.addBody(body);
}
}
let spherebody = new CANNON.Body({
mass: 0,
shape: new CANNON.Sphere(4),
position: new CANNON.Vec3(0,4,0),
material: pubMaterial
})
bodies.push(spherebody);
world.add(spherebody);
for(let i=0; i<Nrows * Ncols; i++) {
let r = Math.floor(i / Nrows);
let c = i % Nrows;
if(r < Nrows - 1) {
world.addConstraint(new CANNON.DistanceConstraint(bodies[r * Nrows + c], b2, dis, 5));
}
if(c < Ncols - 1) {
world.addConstraint(new CANNON.DistanceConstraint(bodies[r * Nrows + c], bodies[r * Nrows + c + 1], dis, 5));
}
}
for(let i=0; i<Nrows * Ncols; i++) {
let mesh = new THREE.Mesh(new THREE.SphereBufferGeometry(size), new THREE.MeshNormalMaterial());
meshes.push(mesh);
scene.add(mesh);
}
let mesh = new THREE.Mesh(new THREE.SphereBufferGeometry(4, 32, 16), new THREE.MeshNormalMaterial());
meshes.push(mesh);
scene.add(mesh);
}
initHinge() {
let bodyA = new CANNON.Body({
mass: 0,
shape: new CANNON.Box(new CANNON.Vec3(0.2, 4, 0.2)),
position: new CANNON.Vec3(-3.2, 5, 0),
material: pubMaterial
})
let bodyB = new CANNON.Body({
mass: 1,
shape: new CANNON.Box(new CANNON.Vec3(3, 4, 0.2)),
position: new CANNON.Vec3(0, 5, 0),
// material: pubMaterial
})
bodyB.velocity.set(0, 0, -10);
bodies.push(bodyA);
bodies.push(bodyB);
world.add(bodyA);
world.add(bodyB);
var c = new CANNON.HingeConstraint(bodyA, bodyB, {
pivotA: new CANNON.Vec3(0.3, 0, 0),
axisA: new CANNON.Vec3(0, 1, 0),
pivotB: new CANNON.Vec3(-3.1, 0, 0),
axisB: new CANNON.Vec3(0, 1, 0),
maxForce: 2
});
world.addConstraint(c);
let meshA = new THREE.Mesh(new THREE.BoxBufferGeometry(0.4, 8, 0.4), new THREE.MeshNormalMaterial());
let meshB = new THREE.Mesh(new THREE.BoxBufferGeometry(6, 8, 0.4), new THREE.MeshNormalMaterial());
meshes.push(meshA);
meshes.push(meshB);
scene.add(meshA);
scene.add(meshB);
}
转载请注明地址:郭先生的博客
three.js cannon.js物理引擎之约束(二)的更多相关文章
- three.js cannon.js物理引擎之ConvexPolyhedron多边形
年后第一天上班,郭先生来说一说cannon.js的ConvexPolyhedron(多边形),cannon.js是一个物理引擎,内部通过连续的计算得到各个时间点的数据的状态,three.js的模型可以 ...
- three.js cannon.js物理引擎之约束
今天郭先生继续说cannon.js,主演内容就是点对点约束和2D坐标转3D坐标.仍然以一个案例为例,场景由一个地面.若干网格组成的约束体和一些拥有初速度的球体组成,如下图.线案例请点击博客原文. 下面 ...
- three.js cannon.js物理引擎之制作拥有物理特性的汽车
今天郭先生说一说使用cannon.js的车辆辅助类让我们的汽车模型拥有物理特性.效果图如下,在线案例请点击博客原文. 下面我们说一下今天要使用的两个类,并简单的看看他们的物理意义 1. Raycast ...
- three.js cannon.js物理引擎之齿轮动画
郭先生今天继续说一说cannon.js物理引擎,并用之前已经学习过的知识实现一个小动画,知识点包括ConvexPolyhedron多边形.Shape几何体.Body刚体.HingeConstraint ...
- three.js cannon.js物理引擎地形生成器和使用指针锁定控件
今天郭先生说一说使用cannon.js物理引擎绘制地形和使用指针锁定控件.效果如下图.线案例请点击博客原文. 这里面的生成地形的插件和指针锁定控件也是cannon.js的作者schteppe封装的,当 ...
- three.js cannon.js物理引擎之Heightfield
今天郭先生说一说cannon.js物理引擎之Heightfield高度场,学过场论的朋友都知道物理学中把某个物理量在空间的一个区域内的分布称为场,高度场就是与高度相关的场,而cannon.js物理引擎 ...
- three.js cannon.js物理引擎制作一个保龄球游戏
关于cannon.js我们已经学习了一些知识,今天郭先生就使用已学的cannon.js物理引擎的知识配合three基础知识来做一个保龄球小游戏,效果如下图,在线案例请点击博客原文. 我们需要掌握的技能 ...
- three.js 之cannon.js物理引擎
今天郭先生说的是一个物理引擎,它十分小巧并且操作简单,没错他就是cannon.js.这些优点都源自于他是基于js编写的,对于js使用者来说cannon.js拥有其他物理引擎没有的纯粹性.从学习成本来看 ...
- 基于Babylon.js编写宇宙飞船模拟程序1——程序基础结构、物理引擎使用、三维罗盘
计划做一个宇宙飞船模拟程序,首先做一些技术准备. 可以访问https://ljzc002.github.io/test/Spacetest/HTML/PAGE/spacetestwp2.html查看测 ...
随机推荐
- java大数函数(附官方文档链接)
java文档 字段摘要 static BigInteger ONE BigInteger 的常量 1. static BigInteger TEN BigInt ...
- 【noi 2.6_2989】糖果(DP)
题意:求取到总和为K的倍数的糖果的最大值. 解法:用模K的余数作为一个维度,f[i][j]表示在前i种糖果中取到总颗数模K余j的最大总颗数. 注意--f[i-1][j]要正常转移,而其他要之前的状态存 ...
- Windows Server 2016 开启远程连接并延长过期时间
按照下面文章配置,做完1.2步即可,其中协议号码填写 4954438 亲测有效! Server 2016默认远程桌面连接数是2个用户,如果多余两个用户进行远程桌面连接时,系统就会提示超过连接数,可以通 ...
- Redis 事务 & 消息队列
Redis 消息队列介绍 什么是消息队列 消息队列(Message Queue)是一种应用间的通信方式,消息发送后可以立即返回,有消息系统来确保信息的可靠传递,消息生产者只管把消息发布到消息队列中而不 ...
- Xtrabackup 物理备份
目录 Xtrabackup 安装 Xtrabackup 备份介绍 Xtrabackup全量备份 准备备份目录 全量备份 查看全量备份内容 Xtrabackup 全量备份恢复数据 删除所有数据库 停止数 ...
- 【python接口自动化】- PyMySQL数据连接
什么是 PyMySQL? PyMySQL是在Python3.x版本中用于连接MySQL服务器的一个库,Python2中则使用mysqldb.它是一个遵循 Python数据库APIv2.0规范, ...
- 从 MFC 移植程序到 wxWidgets 界面库 ——《定时执行专家 5.0》的界面实现
时隔十年的更新,最大的变化就是从 MFC 移植到 wxWidgets,界面也全部重现设计,图标也都进行了更换.wxWidgets(最新版 3.1.4,经典的开源.跨平台 C++ GUI类库)特有的 ...
- 【非原创】codeforces 1070C Cloud Computing 【线段树&树状数组】
题目:戳这里 学习博客:戳这里 题意:有很多个活动,每个活动有持续天数,每个活动会在每天提供C个CPU每个CPU价格为P,问需要工作N天,每天需要K个CPU的最少花费. 解题思路:遍历每一天,维护当前 ...
- HDU - 4462 Scaring the Birds
It's harvest season now! Farmer John plants a lot of corn. There are many birds living around his co ...
- 云原生系列1 pod基础
POD解决了什么问题? 成组资源调度问题的解决. mesos采用的资源囤积策略容易出现死锁和调度效率低下问题:google采用的乐观调度技术难度非常大: 而k8s使用pod优雅的解决了这个问题. po ...