今天郭先生说一说使用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. Socket.IO基础教程

    什么是Socket.IOSocket.IO是一个库,可用于在浏览器和服务器之间进行实时,双向和基于事件的通信。它包括......

  2. nodejs的调试debug

    目录简介开启nodejs的调试调试的安全性使用WebStorm进行nodejs调试使用Chrome devTools......

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

    今天郭先生说一说cannon.js物理引擎之Heightfield高度场,学过场论的朋友都知道物理学中把某个物理量在......

  4. Node.js 安全指南

    当项目周期快结束时,开发人员会越来越关注应用的“安全性”问题。一个安全的应用程序并不是一种奢侈,而是必要的。你应该在......

  5. pixi.js 自定义光标样式

    pixi 介绍Pixi是一个超快的2D渲染引擎,通过Javascript和Html技术创建动画或管理交互式图像,从而......

  6. nodejs事件和事件循环详解

    目录简介nodejs中的事件循环phase详解timerspending callbacksidle, prepar......

  7. 在nodejs中创建child process

    目录简介child process异步创建进程同步创建进程在nodejs中创建child process简介node......

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

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

  9. Neo4j 导入 Nebula Graph 的实践总结

    主要介绍如何通过官方 ETL 工具 Exchange 将业务线上数据从 Neo4j 直接导入到 Nebula Gra......

  10. nodejs中的文件系统

    、目录简介nodejs中的文件系统模块Promise版本的fs文件描述符fs.stat文件状态信息fs的文件读写fs......

随机推荐

  1. Android自定义view仿QQ的Tab按钮动画效果(示例代码)

    话不多说 先上效果图实现其实很简单,先用两张图一张是背景的图,一张是笑脸的图片,笑脸的图片是白色,可能看不出来。实现......

  2. 万万没想到,JVM内存区域的面试题也可以问的这么难?

    二、Java内存区域1、Java内存结构内存结构程序计数器当前线程所执行字节码的行号指示器。若当前方法是native......

  3. java DelayQueue的原理浅析

    在对DelayQueue延迟功能的使用上,很多人不能后完全理解延迟的一些功能使用,这里我们深入来挖掘一下DelayQ......

  4. 使用 C# 9 的records作为强类型ID - 路由和查询参数

    上一篇文章,我介绍了使用 C# 9 的record类型作为强类型id,非常简洁public record Produ......

  5. MYSQL 字符集设置(终端的字符集)

    每次利用终端 创建数据库或者创建表的时候,字符集都是latin1(不指定字符集的时候)如下:查看当前数据库的字符集c......

  6. PHP方法的返回值示例详解

    前言不仅是PHP,大部分编程语言的函数或者叫方法,都可以用return来定义方法的返回值。从函数这个叫法来看,本身它......

  7. C# 获取当前总毫秒数的实例讲解

    在.Net下DateTime.Ticks获得的是个long型的时间整数,具体表示是至0001 年 1 月 1 日午夜......

  8. 用Python自动清理电脑内重复文件,只要10行代码(自动脚本)

    给定一个文件夹,使用Python检查给定文件夹下有无文件重复,若存在重复则删除主要涉及的知识点有:os模块综合应用g......

  9. 用python60行代码写一个简单的笔趣阁爬虫

    系列文章目录python爬虫实战——爬取淘宝商品信息并导入EXCEL表格(超详细)python多线程爬取壁纸 妈妈再......

  10. Java泛型

    你要做一个不动声色的大人了。不准情绪化,不准偷偷想念,不准回头看。去过自己另外的生活。你要听话,不是所有的鱼都会生活......