百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 文章教程 > 正文

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

yund56 2025-07-21 21:24 3 浏览

今天继续说一说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)

相关推荐

[西门子PLC] S7-1200+触摸屏TP700动画:3种办法制作技巧与案例

有同学问:西门子博图精简触摸屏与2个S71200能同时通讯吗?我现在有两个西门子S-1200PLC,想和一个西门子7寸精简型触摸屏通讯。具体该怎么配置,请教一下各位师傅回答:S7-1200和TP700...

HTML5画布类库EaselJS生成鼠标控制的游戏动画人物

第一节:EaselJS生成游戏动画人物效果本节中将使用SpriteSheet和Sprite生成HTML5游戏中的动画人物形象使用SpriteSheet定义动画帧相关的图片,并且使用Sprite定义动画...

一亿家长五星推荐!金牌动画《萌鸡小队》4K大电影来咯

一亿家长五星推荐200亿播放量的金牌动画IP首度亮相大银幕啦合家欢动画电影《萌鸡小队:萌闯新世界》江苏有线4K特别版块全网首播收获成长和友谊理解爱与勇气陪孩子一起快乐冒险吧~来源:江苏有线今日看点...

JavaScript简介:从概念、特点、组成和用法全面带你快速了解JS

“这里是云端源想IT,帮你轻松学IT”嗨~今天的你过得还好吗?我们总是先扬起尘土然后抱怨自己看不见-2024.04.15-JavaScript,简称JS,是一种轻量级的解释型编程语言,它是网页开...

总结100+前端优质库,让你成为前端百事通

1年多时间,陆陆续续整理了一些常用且实用的开源项目,方便大家更高效地学习和工作.js相关库js常用工具类「lodash」一个一致性、模块化、高性能的JavaScript实用工具库。「xij...

实现一个九宫格跳动loading动画 #前端开发

今天来实现一个九宫格跳动loading动画。·九个小方格会不断地交错跳动。·准备一个方块容器,小方块通过js来生成。js动态生成9个小方格,每个方格的动画延迟错开0.1秒。·使用flex布局让整体居中...

Dynamics.js – 创建逼真的物理动画的 JS 库

Dynamics.js是一个用于创建物理动画JavaScript库。你只需要把dynamics.js引入你的页面,然后就可以激活任何DOM元素的CSS属性动画,也可以结合SVG使...

《火影忍者 博人传》动画化决定!OVA将于JSAF2016先行上映!

JUMP人气漫画《火影忍者》虽然说已经完结很久了,但JUMP和岸本貌似没有停下来的节奏。各种原创动画、外传漫画、剧场版动画接二连三地推出,有些火迷们都感觉看腻了。然而这波节奏还没停!据悉,曾经推出过剧...

强大 WebView2 + 不用写 JavaScript 的 htmx.js 「小轻快」开发桌面程序

WebView2是越来越香了。WebView2不但是Win11自带的系统组件,Win10也已经自动推送安装。即使是少量没有安装WebView2的系统——使用aardio中的we...

小学数学老师用DeepSeek做动画课件,一个提示词轻松搞定。

  前几天我分享了一篇关于小学数学老师想做动画课件,DeepSeek-V3让数学知识"动"起来!。这篇文章收到了很多老师的好评,他们直呼好用,并表示学到了很多实用技巧。但也有老师反馈了...

手把手教你H5实现工厂游戏的CSS动画效果「实践」

作者:吴冠禧WecTeam转发连接:https://mp.weixin.qq.com/s/u5GHsA0vHz8A_MmGslRw2g0契机与背景今年Q1(2020年第一季度)参与了京喜事业部「京...

10个帅酷的HTML5最新动画应用(html5简单的动画)

在上个月,我们收集了不少来自国内外的HTML5相关资源和jQuery插件,其中包括很多经典帅酷的HTML5动画应用,有些还利用了Canvas和SVG的相关特性,从而让HTML5动画更加具有强烈的视觉效...

你需要知道的 15 个很棒的 CSS 动画库

从一种CSS样式配置到另一种的过渡可以使用CSS动画进行动画处理。描述CSS动画的样式和指示动画样式的开始和结束状态的一组关键帧,以及可能的中间路点,构成了动画。与传统的脚本驱动动画技术相...

Three.js 实现虎年春节3D创意页面

前言本文由dragonir授权发布,作者还有很多关于Three.js的作品,刚开始看到这个作品,觉得很有趣,虽然对Three.js完全不懂,哈哈,原文地址:https://segmentfault.c...

性能出色,纯CSS实现的loading动画——Loaders.css

介绍loaders.css是Github上一个使用纯粹的css实现的开源loading动画库,完全用CSS编写的加载动画的集合。每个动画仅限于CSS属性的一小部分,以避免复杂的绘画和布局计算。下面这张...