今天郭先生说一说使用cannon.js的车辆辅助类让我们的汽车模型拥有物理特性。效果图如下,在线案例请点击博客原文

下面我们说一下今天要使用的两个类,并简单的看看他们的物理意义

1. RaycastVehicle类

这是车辆辅助类,将光线从车轮位置投射到地面并施加力。它决定车的位置,角度,质量等信息。下面是它的构造函数

RaycastVehicle ( [options] )

options一共有四个参数,并且比较好理解,

  • chassisBody – 表示车身的刚体
  • indexForwardAxis – 前轴索引0 = x,1 = y,2 = z
  • indexRightAxis – 前轴索引0 = x,1 = y,2 = z
  • indexUpAxis – 前轴索引0 = x,1 = y,2 = z

后面的三个参数要决定了车辆哪个方向是前面,,哪个是右面,哪个是上面。比如说我们在three.js中一般以y轴作为向上的方向,因此我们就要将indexUpAxis设置成1,indexRightAxis设置成2。如果有特别的要求,three.js的视图以z轴作为up的方向,这是我们就要将indexUpAxis设置成2,indexRightAxis设置成1(cannon的默认值就是将z轴的方向作为up的方向的)。RaycastVehicle就先说到这,它的一些属性和方向请查看文档。

2. WheelInfo类

这个是车轮类,里面包含了十分丰富的信息,包括车轮相对于车的位置,车轮半径,滚动影响,转弯滑动等等信息,下面我们看一下构造函数

WheelInfo ( [options] )

这个options就很复杂了,可以在我的例子中手动调试。下面我们还是通过案例代码来学习这两个类。

3. 案例代码

先看看物理引擎的部分

var carBodySize = new THREE.Vector3(4.52, 2.26, 1.08);
var wheelRadius = 0.5;
initCannon() {
//初始物理里世界
world = new CANNON.World();
world.quatNormalizeSkip = 0;
world.quatNormalizeFast = false;
world.gravity.set(0, 0, -9.8);
world.broadphase = new CANNON.NaiveBroadphase();
world.solver.iterations = 10;
world.defaultContactMaterial.friction = 0;
//定义车体形状
var chassisShape;
//车体为一个矩形
chassisShape = new CANNON.Box(new CANNON.Vec3(carBodySize.x/2, carBodySize.y/2, carBodySize.z/2));
//定义车体刚体
var chassisBody = new CANNON.Body({mass: 150, material: new CANNON.Material({friction: 0, restitution: 0})})
//刚体中添加形状
chassisBody.addShape(chassisShape);
//初始化刚体的位置
chassisBody.position.set(0, 0, 5);
//设置一个初始的角速度
chassisBody.angularVelocity.set(0, 0, 0.5);
//初始化车辆引擎
vehicle = new CANNON.RaycastVehicle({
chassisBody: chassisBody, indexForwardAxis: 0, indexRightAxis: 1, indexUpAxis: 2
}); var options = {
radius: wheelRadius,
directionLocal: new CANNON.Vec3(0, 0, -wheelRadius * 2),
suspensionStiffness: 30,
suspensionRestLength: 0.3,
frictionSlip: 5,
dampingRelaxation: 2.3,
dampingCompression: 4.4,
maxSuspensionForce: 100000,
rollInfluence: 0.01,
axleLocal: new CANNON.Vec3(0, 1, 0),
chassisConnectionPointLocal: new CANNON.Vec3(1, 1, 0),
maxSuspensionTravel: 0.3,
customSlidingRotationalSpeed: -30,
useCustomSlidingRotationalSpeed: true
};
//设置第一个轮的位置,并将轮子信息添加到车辆类中
options.chassisConnectionPointLocal.set(1.13, 0.95, -0.1);
vehicle.addWheel(options);
//设置第二个轮的位置,并将轮子信息添加到车辆类中
options.chassisConnectionPointLocal.set(1.13, -0.95, -0.1);
vehicle.addWheel(options);
//设置第三个轮的位置,并将轮子信息添加到车辆类中
options.chassisConnectionPointLocal.set(-1.47, 0.95, -0.05);
vehicle.addWheel(options);
//设置第四个轮的位置,并将轮子信息添加到车辆类中
options.chassisConnectionPointLocal.set(-1.47, -0.95, -0.05);
vehicle.addWheel(options);
//通过addToWorld方法将将车辆及其约束添加到世界上。
vehicle.addToWorld(world);
//高度场的方法,上节已经了解了,不多说
var matrix = [];
for (var i = 0; i < size; i++) {
matrix.push([]);
for (var j = 0; j < size; j++) {
var height = Math.cos(i / size * Math.PI * (size / 10)) * Math.cos(j / size * Math.PI * (size / 10)) / 2;
matrix[i].push(height)
}
}
var hfShape = new CANNON.Heightfield(matrix, {
elementSize: 1
});
var hfBody = new CANNON.Body({ mass: 0, material: new CANNON.Material({friction: 0.5, restitution: 0})});
hfBody.addShape(hfShape, new CANNON.Vec3(-size / 2, - size / 2, 0), new CANNON.Quaternion());
world.addBody(hfBody);
},

接下来是操作小汽车的一些代码

document.onkeydown = this.handler;
document.onkeyup = this.handler;
handler(event) {
var up = (event.type == 'keyup');
if(!up && event.type !== 'keydown'){
return;
} vehicle.setBrake(0, 0);
vehicle.setBrake(0, 1);
vehicle.setBrake(0, 2);
vehicle.setBrake(0, 3); switch(event.keyCode){
case 38: // 按下向前键时,通过applyEngineForce方法,设置车轮力以在每个步骤中施加在后车轮上
vehicle.applyEngineForce(up ? 0 : -params.maxForce, 2);
vehicle.applyEngineForce(up ? 0 : -params.maxForce, 3);
break; case 40: // 同上
vehicle.applyEngineForce(up ? 0 : params.maxForce, 2);
vehicle.applyEngineForce(up ? 0 : params.maxForce, 3);
break; case 66: // 刹车键b,通过setBrake方法,设置四个车轮的制动力
vehicle.setBrake(brakeForce, 0);
vehicle.setBrake(brakeForce, 1);
vehicle.setBrake(brakeForce, 2);
vehicle.setBrake(brakeForce, 3);
break; case 39: // 按下右键,通过setSteeringValue方法,设置前轮转向值
vehicle.setSteeringValue(up ? 0 : -maxSteerVal, 0);
vehicle.setSteeringValue(up ? 0 : -maxSteerVal, 1);
break; case 37: // 同上
vehicle.setSteeringValue(up ? 0 : maxSteerVal, 0);
vehicle.setSteeringValue(up ? 0 : maxSteerVal, 1);
break;
}
},

好的这就是主要代码,小车是在THREE的官方demo上面下载的。

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

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物理引擎的知识配合three基础知识来做一个保龄球小游戏,效果如下图,在线案例请点击博客原文. 我们需要掌握的技能 ...

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

    郭先生今天继续说一说cannon.js物理引擎,并用之前已经学习过的知识实现一个小动画,知识点包括ConvexPolyhedron多边形.Shape几何体.Body刚体.HingeConstraint ...

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

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

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

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

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

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

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

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

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

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

  9. 造个海洋球池来学习物理引擎【Three.js系列】

    github地址:https://github.com/hua1995116/Fly-Three.js 大家好,我是秋风.继上一篇<Three.js系列:   游戏中的第一/三人称视角>今 ...

随机推荐

  1. JAVA基础之接口

    接口 学习完框架之后,整合SSM过程中对于接口的认识加深了许多.根据<java核心技术>这本书进一步研究了一下. 1.概念 java核心技术是这样说的:"在Java程序设计中,接 ...

  2. 51 张图助你彻底掌握 HTTP!

    前言 如果说 TCP/IP 协议是互联网通信的根基,那么 HTTP 就是其中当之无愧的王者,小到日常生活中的游戏,新闻,大到双十一秒杀等都能看到它的身影,据 NetCraft 统计,目前全球至少有 1 ...

  3. 负载均衡各个算法JAVA诠释版

    00 前言 首先给大家介绍下什么是负载均衡(来自百科) 负载均衡建立在现有网络结构之上,它提供了一种廉价有效透明的方法扩展 网络设备和 服务器的带宽.增加 吞吐量.加强网络数据处理能力.提高网络的灵活 ...

  4. Databricks 第四篇:分组统计和窗口

    对数据分析时,通常需要对数据进行分组,并对每个分组进行聚合运算.在一定意义上,窗口也是一种分组统计的方法. 分组数据 DataFrame.groupBy()返回的是GroupedData类,可以对分组 ...

  5. 【C++】《C++ Primer 》第十六章

    第十六章 模板与泛型编程 面向对象编程和泛型编程都能处理在编写程序时不知道类型的情况. OOP能处理类型在程序允许之前都未知的情况. 泛型编程在编译时就可以获知类型. 一.定义模板 模板:模板是泛型编 ...

  6. 【Vue】Vue开发环境搭建

    Vue前置学习环境 文章目录 Vue前置学习环境 IDE Node.js 调试环境 工程环境 小结 IDE WebStorm 官网下载:https://www.jetbrains.com/websto ...

  7. 【Java】计算机软件、博客的重要性、编程语言介绍和发展史

    之前学得不踏实,重新复习一遍,打扎实基础中. 记录 Java核心技术-宋红康_2019版 & Java零基础学习-秦疆 文章目录 软件开发介绍 软件开发 什么是计算机? 硬件及冯诺依曼结构 计 ...

  8. 记一次centos7重启后docker无法启动的问题

    问题描述 在重新了centos7系统后,docker突然就启动不了了,查看报错信息 [root@localhost ~]# systemctl status docker.service ● dock ...

  9. python—base64

    今天在写题时,执行脚本又报错了 脚本如下 #! /usr/bin/env python3 # _*_ coding:utf-8 _*_ import base64 # 字典文件路径 dic_file_ ...

  10. [Usaco2007 Dec]Building Roads 修建道路

    题目描述 Farmer John最近得到了一些新的农场,他想新修一些道路使得他的所有农场可以经过原有的或是新修的道路互达(也就是说,从任一个农场都可以经过一些首尾相连道路到达剩下的所有农场).有些农场 ...