当前位置:首页 > 技术分析 > 正文内容

three.js cannon.js物理引擎之齿轮动画

ruisui884个月前 (01-14)技术分析24

今天继续说一说cannon.js物理引擎,并用之前已经学习过的知识实现一个小动画,知识点包括ConvexPolyhedron多边形、Shape几何体、Body刚体、HingeConstraint铰链约束等等知识。因为我之前用纯three.js 的THREEBSP实现过一个静态的齿轮,现在就想配合cannon.js让它的转动更加的符合实际而不是匀速转动。下面我们来说说我们要做的这个案例,这个小案例是由5个齿轮组成,最左面的是有动力的齿轮,我们可以控制它的速度,而右面三个齿轮是可以移动的,我们可以自由移动(有点类似于变速箱),嗯就是怎么简单。下面我们来说一说这个是怎么实现的,效果如下图,在线案例请点击博客原文。

1. three.js 实现齿轮模型

three.js几何体在最前面我已经说过了,实现一个这样的模型(在不考虑引用模型的情况下),我们可以考虑直接使用Geometry来绘制或者向THREE.Group()对象中添加基础几何体来绘制,这里我们使用第二种方法。这里的思路就是使用ConvexGeometry凸包做出锯齿的齿,然后使用圆柱填充即可,如下图,

下面是相关部分代码

var meshA, meshB, meshC, meshD, meshE;
var bodyA, bodyB, bodyC, bodyD, bodyE;
var axleA, axleB, axleC, axleD, axleE;
var pos = [-8.5, 0], pos1 = [6.4, 8], pos2 = [8.5, 0], pos3 = [10.6, -13];
var radius1 = 2, radius2 = 4, radius3 = 6;
var length = 0.5, thickness = 3;
var sin375 = 0.075, cos375 = 0.997;
var sin75 = 0.131, cos75 = 0.991;
var sin15 = 0.259, cos15 = 0.966;
var params = {
    positionX: 0,
    positionY: 0,
    speed: 1,
}
var triangleMesh1 = this.getTriangleMesh(sin15, cos15, radius1);
var triangleMesh2 = this.getTriangleMesh(sin75, cos75, radius2);
var triangleMesh3 = this.getTriangleMesh(sin375, cos375, radius3);
meshA = new THREE.Group();
meshB = new THREE.Group();
meshC = new THREE.Group();
meshD = new THREE.Group();
meshE = new THREE.Group();
for(let i=0; i<24; i++) {
    let angle = Math.PI * 2 * i * 15 / 360;
    let itemMesh = triangleMesh2.clone();
    itemMesh.rotation.z = angle;
    meshA.add(itemMesh.clone());
    meshB.add(itemMesh.clone());
    meshD.add(itemMesh.clone());
}
for(let i=0; i<12; i++) {
    let angle = Math.PI * 2 * i * 30 / 360;
    let itemMesh = triangleMesh1.clone();
    itemMesh.rotation.z = angle;
    meshC.add(itemMesh.clone());
}
for(let i=0; i<48; i++) {
    let angle = Math.PI * 2 * i * 7.5 / 360;
    let itemMesh = triangleMesh3.clone();
    itemMesh.rotation.z = angle;
    meshE.add(itemMesh.clone());
}
let cylindMesh1 = new THREE.Mesh(new THREE.CylinderGeometry(radius1,radius1,thickness,32,1), new THREE.MeshNormalMaterial());
let cylindMesh2 = new THREE.Mesh(new THREE.CylinderGeometry(radius2,radius2,thickness,32,1), new THREE.MeshNormalMaterial());
let cylindMesh3 = new THREE.Mesh(new THREE.CylinderGeometry(radius3,radius3,thickness,32,1), new THREE.MeshNormalMaterial());
cylindMesh1.rotation.x = Math.PI / 2;
cylindMesh2.rotation.x = Math.PI / 2;
cylindMesh3.rotation.x = Math.PI / 2;
meshA.add(cylindMesh2.clone());
meshB.add(cylindMesh2.clone());
meshC.add(cylindMesh1.clone());
meshD.add(cylindMesh2.clone());
meshE.add(cylindMesh3.clone());
let cylindMesh = new THREE.Mesh(new THREE.CylinderGeometry(0.5,0.5,10,6,1), new THREE.MeshPhongMaterial({color: 0xffcc77, flatShading: true}));
cylindMesh.rotation.x = Math.PI / 2;
meshA.add(cylindMesh.clone());
meshB.add(cylindMesh.clone());
meshC.add(cylindMesh.clone());
meshD.add(cylindMesh.clone());
meshE.add(cylindMesh.clone());
scene.add(meshA);
scene.add(meshB);
scene.add(meshC);
scene.add(meshD);
scene.add(meshE);
getTriangleMesh(sin, cos, radius) {
    var pointsArr = [[sin * radius, cos * radius, thickness / 2], [sin * radius, cos * radius, -thickness / 2], [-sin * radius, cos * radius, thickness / 2], [-sin * radius, cos * radius, -thickness / 2], [0, radius + length, thickness / 2], [0, radius + length, -thickness / 2]];
    var points = pointsArr.map(d => new THREE.Vector3(d[0],d[1],d[2]));
    var triangle = new ConvexGeometry(points);
    return new THREE.Mesh(triangle, new THREE.MeshNormalMaterial());;
},

2. 添加cannon.js物理引擎

这里就要用到前面两篇的内容了,一个是HingeConstraint铰链约束,另一是ConvexPolyhedron多边形。齿轮沿着轴旋转,我们通过铰链约束把齿轮和轴约束到一起,让齿轮仅沿着轴的方向转动,接下来是通过ConvexPolyhedron多边形制作出齿轮的齿,然后通过Body的addShape方法,将齿轮的齿添加到刚体中。思路其实是很简单的,不过里面有一些小计算。
下面我们看代码

//齿轮齿的shape
let verts = [
    new CANNON.Vec3(-sin75 * radius1, -(radius1 + length - cos75 * radius1) / 2, thickness / 2),
    new CANNON.Vec3(0, (radius1 + length - cos75 * radius1) / 2, thickness / 2),
    new CANNON.Vec3(sin75 * radius1, -(radius1 + length - cos75 * radius1) / 2, thickness),
    new CANNON.Vec3(-sin75 * radius1, -(radius1 + length - cos75 * radius1) / 2, -thickness / 2),
    new CANNON.Vec3(0, (radius1 + length - cos75 * radius1) / 2, -thickness / 2),
    new CANNON.Vec3(sin75 * radius1, -(radius1 + length - cos75 * radius1) / 2, -thickness / 2),
];
let faces = [[0,2,1], [3,4,5], [0,1,3], [1,4,3], [5,4,1], [2,5,1], [3,5,2], [3,2,0]];
let shape = new CANNON.ConvexPolyhedron(verts, faces);
//齿轮的轴
axleA = new CANNON.Body({
    mass: 0,
    position: new CANNON.Vec3(pos[0], pos[1], 0),
    shape: new CANNON.Cylinder(0.1, 0.1, 1, 3),
})
//齿轮刚体
bodyA = new CANNON.Body({
    mass: 1,
    position: new CANNON.Vec3(pos[0], pos[1], 0)
})
//为齿轮刚体添加齿
for(let i=0; i<12; i++) {
    let angle = i / 12 * Math.PI * 2;
    let x = Math.sin(angle) * (cos15 * radius1 + (radius1 + length - cos15 * radius1) / 2);
    let y = Math.cos(angle) * (cos15 * radius1 + (radius1 + length - cos15 * radius1) / 2);
    bodyC.addShape(shape, new CANNON.Vec3(x, y, 0), new CANNON.Quaternion().setFromEuler(0, 0, -angle));
}
//为轮和齿设置铰链约束
var c1 = new CANNON.HingeConstraint(axleA, bodyA, { 
    pivotA: new CANNON.Vec3(0, 0, 0),
    axisA: new CANNON.Vec3(0, 0, 1),
    pivotB: new CANNON.Vec3(0, 0, 0),
    axisB: new CANNON.Vec3(0, 0, 1),
    maxForce: 100
});
world.addConstraint(c1);
//让齿轮不断的动起来
bodyA.angularVelocity.set(0, 0, params.speed);

然后在制作其他四个齿轮,然后放在不同的位置,在通过gui设置一些可操作项。这样我们就完成了一个简单的齿轮机组了,这一系列的cannon.js的文章应该还剩一两篇。希望大家都掌握好。

转载自:郭先生的博客(https://www.mrguo.link/article?id=57)

扫描二维码推送至手机访问。

版权声明:本文由ruisui88发布,如需转载请注明出处。

本文链接:http://www.ruisui88.com/post/259.html

标签: threebsp
分享给朋友:

“three.js cannon.js物理引擎之齿轮动画” 的相关文章

5个看起来像 MacOS 的 Linux 发行版,赶紧收藏!

既想使用 Linux,又想同时使用 Mac ?那么你可以尝试这些 Linux 发行版,你肯定会觉得自己在用 Mac 系统。1. Elementry OSElementry OS 是看起来像 Mac OS 的最好的 Linux 发行版。和 Mac 一样,这个操作系统也是为了保护隐私而设计的。因此你会得...

深入理解Vue.js组件通信:父子组件与子父组件数据交互详解

什么是Vue组件通讯 Vue.js 组件通信是指在 Vue 应用的不同组件之间进行数据交换和状态同步的过程。由于 Vue 的组件是基于单文件组件(SFCs)的模块化设计,每个组件都有自己的作用域,因此它们不能直接访问彼此的数据。为了使组件之间能够协同工作,Vue 提供了几种不同的通信方式。以下是 V...

Gitlab概览

Gitlab是开源的基于Git的仓库管理系统,也可以管理软件开发的整个生命周期,是项目管理和代码托管平台,支撑着整个DevOps的生命周期。Gitlab很容易选为GitHub,作为公司私有库管理的工具。我们可以用Gitlab Workflow来协同整个团队的软件开发管理过程。软件开发阶段Gitlab...

Acustica Audio 发布模拟Roland Jupiter 双声道合成器插件 TH2

福利: Acustica Audio 发布模拟Roland Jupiter 风格的双声道合成器插件 TH2 免费下载 意大利 Acustica Audio 公司发布布模拟Roland Jupiter 风格的双声道合成器插件 TH2 ,灵感来源于Acustica Audio的THING-8系列,它是...

「干货」FPGA设计中深度约束技巧及调试经验总结

今天跟大家分享的内容很重要,也是我们调试FPGA经验的总结。随着FPGA对时序和性能的要求越来越高,高频率、大位宽的设计越来越多。在调试这些FPGA样机时,需要从写代码时就要小心谨慎,否则写出来的代码可能无法满足时序要求。另外,最近跟网友聊天时,有谈到公众号寿命的问题,我觉得网络交换FPGA公众号应...

雅马哈TMAX 560 TECH MAX 外媒深度测评

应雅马哈(Yamaha)的邀请,在葡萄牙埃斯托里尔对全新的Yamaha TMAX 560 Tech Max踏板车进行了测试,在这里TMAX 560 Tech Max售价为11649英镑。雅马哈TMAX长期以来一直站在踏板车的顶端,就声誉和知名度而言,它是当之无愧的大踏板界NO.1。2020 TMAX...