郭先生今天继续说一说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的文章应该还剩一两篇。希望大家都掌握好。

转载请注明地址:郭先生的博客

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

  1. three.js cannon.js物理引擎之ConvexPolyhedron多边形

    年后第一天上班,郭先生来说一说cannon.js的ConvexPolyhedron(多边形),cannon.js是一个物理引擎,内部通过连续的计算得到各个时间点的数据的状态,three.js的模型可以 ...

  2. three.js cannon.js物理引擎地形生成器和使用指针锁定控件

    今天郭先生说一说使用cannon.js物理引擎绘制地形和使用指针锁定控件.效果如下图.线案例请点击博客原文. 这里面的生成地形的插件和指针锁定控件也是cannon.js的作者schteppe封装的,当 ...

  3. three.js cannon.js物理引擎之Heightfield

    今天郭先生说一说cannon.js物理引擎之Heightfield高度场,学过场论的朋友都知道物理学中把某个物理量在空间的一个区域内的分布称为场,高度场就是与高度相关的场,而cannon.js物理引擎 ...

  4. three.js cannon.js物理引擎之制作拥有物理特性的汽车

    今天郭先生说一说使用cannon.js的车辆辅助类让我们的汽车模型拥有物理特性.效果图如下,在线案例请点击博客原文. 下面我们说一下今天要使用的两个类,并简单的看看他们的物理意义 1. Raycast ...

  5. three.js cannon.js物理引擎制作一个保龄球游戏

    关于cannon.js我们已经学习了一些知识,今天郭先生就使用已学的cannon.js物理引擎的知识配合three基础知识来做一个保龄球小游戏,效果如下图,在线案例请点击博客原文. 我们需要掌握的技能 ...

  6. three.js cannon.js物理引擎之约束

    今天郭先生继续说cannon.js,主演内容就是点对点约束和2D坐标转3D坐标.仍然以一个案例为例,场景由一个地面.若干网格组成的约束体和一些拥有初速度的球体组成,如下图.线案例请点击博客原文. 下面 ...

  7. three.js cannon.js物理引擎之约束(二)

    今天郭先生继续讲cannon.js的物理约束,之前的一篇文章曾简单的提及过PointToPointConstraint约束,那么今天详细的说一说cannon.js的约束和使用方法.在线案例请点击博客原 ...

  8. three.js 之cannon.js物理引擎

    今天郭先生说的是一个物理引擎,它十分小巧并且操作简单,没错他就是cannon.js.这些优点都源自于他是基于js编写的,对于js使用者来说cannon.js拥有其他物理引擎没有的纯粹性.从学习成本来看 ...

  9. 基于Babylon.js编写宇宙飞船模拟程序1——程序基础结构、物理引擎使用、三维罗盘

    计划做一个宇宙飞船模拟程序,首先做一些技术准备. 可以访问https://ljzc002.github.io/test/Spacetest/HTML/PAGE/spacetestwp2.html查看测 ...

随机推荐

  1. B. Queue

    During the lunch break all n Berland State University students lined up in the food court. However, ...

  2. Cyclic Nacklace HDU - 3746

    CC这个月底总是很郁闷,昨天他查了他的信用卡,没有任何意外,只剩下99.9元了.他很苦恼,想着如何度过这最后的几天.受"HDU CakeMan"企业家精神的启发,他想卖一些小东西来 ...

  3. Codeforces Round #570 (Div. 3) E. Subsequences (easy version) (搜索,STL)

    题意:有一长度为\(n\)的字符串,要求得到\(k\)不同的它的子序列(可以是空串),每个子序列有\(|n|-|t|\)的贡献,求合法情况下的最小贡献. 题解:直接撸个爆搜找出所有子序列然后放到set ...

  4. Operating System:操作系统启动总结

    现代操作系统的启动引导过程会有所差异,本文仅针对Intel x86系列作讲解,了解原理即可. 系统引导过程总体介绍 系统引导过程主要由以下几个步骤组成(以硬盘启动为例)1.开机:2.BIOS加电自检( ...

  5. Ubuntu——常用命令

    一.进入文件夹 1.cd .. # 进入上一个文件夹 2.cd ../.. # 进入上两个文件夹 3.cd - # 去到进入当前文件夹之前的那个文件夹 二.复制文件 cp 目标文件 复制文件名 三.移 ...

  6. kubernetes实战-交付dubbo服务到k8s集群(六)使用blue ocean流水线构建dubbo-consumer服务

    我们这里的dubbo-consumer是dubbo-demo-service的消费者: 我们之前已经在jenkins配置好了流水线,只需要填写参数就行了. 由于dubbo-consumer用的gite ...

  7. WOJ1024 (POJ1985+POJ2631) Exploration 树/BFS

    title: WOJ1024 (POJ1985+POJ2631) Exploration 树/BFS date: 2020-03-20 10:43:00 categories: acm tags: [ ...

  8. C++ STL (基础)

    STL是什么(STL简介) 本节主要讲述 STL 历史.STL 组件.STL 基本结构以及 STL 编程概述.STL 历史可以追溯到 1972 年 C 语言在 UNIX 计算机上的首次使用.直到 19 ...

  9. 【DP】区间DP入门

    在开始之前我要感谢y总,是他精彩的讲解才让我对区间DP有较深的认识. 简介 一般是线性结构上的对区间进行求解最值,计数的动态规划.大致思路是枚举断点,然后对断点两边求取最优解,然后进行合并从而得解. ...

  10. CNN可视化技术总结(四)--可视化工具与项目

    CNN可视化技术总结(一)-特征图可视化 CNN可视化技术总结(二)--卷积核可视化 CNN可视化技术总结(三)--类可视化 导言: 前面介绍了可视化的三种方法--特征图可视化,卷积核可视化,类可视化 ...