当前位置: 首页 > news >正文

Cannon-ES中RaycastVehicle的深入探索与实践

本文目录

  • 前言
  • 1、RaycastVehicle
    • 1.1 概念
    • 1.2 核心特性
    • 1.3 应用场景
  • 2、前置代码准备
  • 3、RaycastVehicle的使用
    • 3.1 代码
    • 3.2 效果
  • 4、监听施加力
    • 4.1 代码
    • 4.2 效果

前言

在三维物理引擎的世界里,Cannon-ES以其轻量级、高效和易于集成的特点,赢得了众多开发者的青睐。而RaycastVehicle,作为Cannon-ES中用于模拟复杂车辆运动的核心类,更是为开发者提供了强大的车辆动力学模拟功能。从简单的汽车驾驶到复杂的赛车游戏,RaycastVehicle都能轻松应对。
本文将带您深入探索RaycastVehicle的概念、核心特性和应用场景。我们将从理论到实践,逐步揭示RaycastVehicle的奥秘。通过详细的代码示例和效果展示,您将看到RaycastVehicle如何在Cannon-ES的物理世界中模拟出逼真的车辆运动。此外,我们还将探讨如何监听和施加力,以实现更加丰富的车辆交互效果。
无论您是Cannon-ES的新手,还是已经有一定经验的开发者,本文都将为您提供宝贵的参考和启示。让我们一起踏上这段探索之旅,共同领略RaycastVehicle的魅力吧!

1、RaycastVehicle

Cannon-es中,RaycastVehicle是一个重要的概念,它允许开发者在物理世界中模拟复杂的车辆运动。

1.1 概念

RaycastVehicleCannon-es中用于模拟车辆运动的类。它通过使用射线投射(Raycasting)技术来确定车辆与地面的接触点,并据此计算车辆的物理行为。这种技术使得RaycastVehicle能够处理各种复杂的地形和物理交互。

1.2 核心特性

  1. 射线投射技术:RaycastVehicle利用射线投射来确定车辆与地面的接触点。这些射线从车辆底部的多个点发出,并沿着车辆的运动方向投射到地面上。通过检测这些射线与地面的交点,RaycastVehicle能够计算出车辆的支撑点和摩擦力等物理参数。
  2. 多轮支持:RaycastVehicle支持多轮车辆模拟,这意味着它可以处理具有多个轮子的车辆。每个轮子都可以独立地进行射线投射和物理计算,从而更准确地模拟车辆的运动。
  3. 物理行为模拟:RaycastVehicle能够模拟车辆的多种物理行为,包括加速、减速、转向、碰撞等。这些行为都是基于物理原理进行计算的,因此能够呈现出逼真的车辆运动效果。

1.3 应用场景

RaycastVehicleCannon-es中具有广泛的应用场景,特别是在需要模拟车辆运动的3D物理模拟中。以下是一些典型的应用场景:

  • 游戏开发:在游戏开发中,RaycastVehicle可以用于模拟玩家的车辆控制。通过模拟车辆的物理行为,游戏可以提供更加逼真的驾驶体验。
  • 虚拟现实:在虚拟现实应用中,RaycastVehicle可以用于模拟用户在虚拟环境中的车辆驾驶。这可以增强用户的沉浸感和交互体验。
  • 物理模拟:在物理模拟领域,RaycastVehicle可以用于研究和分析车辆在不同条件下的运动特性。这有助于优化车辆设计、提高车辆性能以及确保车辆的安全性。

2、前置代码准备

<template><canvas ref="cannonDemo" class="cannonDemo"></canvas>
</template><script setup>
import { onMounted, ref } from "vue"
import * as THREE from 'three'
import * as CANNON from 'cannon-es'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
const cannonDemo = ref('null')onMounted(() => {const cannonDemoDomWidth = cannonDemo.value.offsetWidthconst cannonDemoDomHeight = cannonDemo.value.offsetHeight// 创建场景const scene = new THREE.Scene// 创建相机const camera = new THREE.PerspectiveCamera( // 透视相机45, // 视角 角度数cannonDemoDomWidth / cannonDemoDomHeight, // 宽高比 占据屏幕0.1, // 近平面(相机最近能看到物体)1000, // 远平面(相机最远能看到物体))camera.position.set(0, 2, 40)// 创建渲染器const renderer = new THREE.WebGLRenderer({antialias: true, // 抗锯齿canvas: cannonDemo.value})// 设置设备像素比renderer.setPixelRatio(window.devicePixelRatio)// 设置画布尺寸renderer.setSize(cannonDemoDomWidth, cannonDemoDomHeight)const light = new THREE.AmbientLight(0x404040, 200); // 柔和的白光scene.add(light);let meshes = []let phyMeshes = []const physicsWorld = new CANNON.World()// 设置y轴重力physicsWorld.gravity.set(0, -9.82, 0)const planeShap = new CANNON.Plane()const planeBody = new CANNON.Body({shape: planeShap,mass: 0,type: CANNON.BODY_TYPES.STATIC,position: new CANNON.Vec3(0, 0, 0)})planeBody.quaternion.setFromAxisAngle(new CANNON.Vec3(1, 0, 0), -Math.PI / 2)physicsWorld.addBody(planeBody)phyMeshes.push(planeBody)const planeGeometry = new THREE.PlaneGeometry(100, 100)const planeMaterial = new THREE.MeshBasicMaterial({ color: 0xE0E0E0, side: THREE.DoubleSide })const planeMesh = new THREE.Mesh(planeGeometry, planeMaterial)scene.add(planeMesh)meshes.push(planeMesh)const axesHelper = new THREE.AxesHelper(30);scene.add(axesHelper);const updatePhysic = () => { // 因为这是实时更新的,所以需要放到渲染循环动画animate函数中physicsWorld.step(1 / 60)for (let i = 0; i < phyMeshes.length; i++) {meshes[i].position.copy(phyMeshes[i].position)meshes[i].quaternion.copy(phyMeshes[i].quaternion)}}// 控制器const control = new OrbitControls(camera, renderer.domElement)// 开启阻尼惯性,默认值为0.05control.enableDamping = true// 渲染循环动画function animate() {// 在这里我们创建了一个使渲染器能够在每次屏幕刷新时对场景进行绘制的循环(在大多数屏幕上,刷新率一般是60次/秒)requestAnimationFrame(animate)updatePhysic()// 更新控制器。如果没在动画里加上,那必须在摄像机的变换发生任何手动改变后调用control.update()renderer.render(scene, camera)}// 执行动画animate()
})</script>
<style scoped>
.cannonDemo {width: 100vw;height: 100vh;
}
</style>

我们也是初始化了整个场景,并且放了平面。


3、RaycastVehicle的使用

3.1 代码

创建悬架车架及轮子,代码如下:

    // 创建车身let chassisShape = new CANNON.Box(new CANNON.Vec3(2,0.5,1))let chassisBody = new CANNON.Body({mass: 1,shape: chassisShape,position: new CANNON.Vec3(0, 5, 0)})physicsWorld.addBody(chassisBody)phyMeshes.push(chassisBody)// 创建视图车身let chassisMesh = new THREE.Mesh(new THREE.BoxGeometry(4,1,2),new THREE.MeshBasicMaterial({color: 0x0000ff}))scene.add(chassisMesh)meshes.push(chassisMesh)// 创建复杂车架const vehicle = new CANNON.RaycastVehicle({chassisBody: chassisBody})// 车轮配置const wheelOptions = {// 半径radius: 0.5,// 车轮垂直哪个轴directionLocal: new CANNON.Vec3(0, -1, 0),// 设置悬架刚度suspensionStiffness: 30,// 设置悬架的休息长度suspensionRestLength: 0.5,// 设置车轮的滑动摩擦力frictionSlip: 1.5,// 悬架拉伸阻尼dampingRelaxation: 2.3,// 悬架压缩阻尼dampingCompression: 4.3,// 最大悬架力maxSuspensionForce: 100000,// 设置最大的悬架变化maxSuspensionTravel: 0.3,// 设置车轮的转向轴axleLocal: new CANNON.Vec3(0,0,1)}// 添加vehicle.addWheel({...wheelOptions,// 车轮位置chassisConnectionPointLocal: new CANNON.Vec3(-1,0,1)})vehicle.addWheel({...wheelOptions,// 车轮位置chassisConnectionPointLocal: new CANNON.Vec3(-1,0,-1)})vehicle.addWheel({...wheelOptions,// 车轮位置chassisConnectionPointLocal: new CANNON.Vec3(1,0,1)})vehicle.addWheel({...wheelOptions,// 车轮位置chassisConnectionPointLocal: new CANNON.Vec3(1,0,-1)})vehicle.addToWorld(physicsWorld)// 车轮形状const wheelShape = new CANNON.Cylinder(0.5,0.5,0.2,20);const wheelGeometry = new THREE.CylinderGeometry(0.5,0.5,0.2,20)const wheelMaterial = new THREE.MeshBasicMaterial({color: 0x888888})let wheelBodies = []for(let i = 0; i < vehicle.wheelInfos.length; i++) {const wheel = vehicle.wheelInfos[i]const cylinderBody = new CANNON.Body({mass: 0,shape: wheelShape})cylinderBody.position.copy(wheel.chassisConnectionPointWorld)cylinderBody.quaternion.copy(chassisBody.quaternion)// physicsWorld.addBody(cylinderBody)phyMeshes.push(cylinderBody)wheelBodies.push(cylinderBody)const cylinderMesh = new THREE.Mesh(wheelGeometry, wheelMaterial)cylinderMesh.rotation.x = -Math.PI/2const wheelObj = new THREE.Object3D()wheelObj.add(cylinderMesh)scene.add(wheelObj)meshes.push(wheelObj)}physicsWorld.addEventListener('postStep', () => {for(let i = 0; i < vehicle.wheelInfos.length; i++) {vehicle.updateWheelTransform(i)const t = vehicle.wheelInfos[i].worldTransformconst wheelBody = wheelBodies[i]wheelBody.position.copy(t.position)wheelBody.quaternion.copy(t.quaternion)}
})

3.2 效果

请添加图片描述


4、监听施加力

4.1 代码

我们监听事件以便给车子施加力,代码如下:

window.addEventListener('keydown', (event) => {if (event.key == 'w') {vehicle.applyEngineForce(-100, 0)vehicle.applyEngineForce(-100, 1)}if (event.key == 's') {vehicle.applyEngineForce(100, 0)vehicle.applyEngineForce(100, 1)}if (event.key == 'a') {vehicle.setSteeringValue(Math.PI/4, 0)vehicle.setSteeringValue(Math.PI/4, 1)}if (event.key == 'd') {vehicle.setSteeringValue(-Math.PI/4, 0)vehicle.setSteeringValue(-Math.PI/4, 1)}})window.addEventListener('keyup', (event) => {if (event.key == 'w') {vehicle.applyEngineForce(0, 0)vehicle.applyEngineForce(0, 1)}if (event.key == 's') {vehicle.applyEngineForce(0, 0)vehicle.applyEngineForce(0, 1)}if (event.key == 'a') {vehicle.setSteeringValue(0, 0)vehicle.setSteeringValue(0, 1)}if (event.key == 'd') {vehicle.setSteeringValue(0, 0)vehicle.setSteeringValue(0, 1)}})

4.2 效果

请添加图片描述

在学习的路上,如果你觉得本文对你有所帮助的话,那就请关注点赞评论三连吧,谢谢,你的肯定是我写博的另一个支持。

原文地址:https://blog.csdn.net/weixin_44103733/article/details/142761941
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mrgr.cn/news/45737.html

相关文章:

  • 2024_10_8 系统进展
  • python学习记录8
  • MES系统:制造业的智能大脑
  • Java中对象和对象变量
  • 【深度学习】yolov8n模型的剪枝操作记录
  • 职场中的人情世故,你懂了多少?
  • mikrotik ROS container 容器可用的URL
  • windows配置java环境变量
  • D31【python 接口自动化学习】- python基础之输入输出与文件操作
  • VM虚拟机安装 CentOS 7.6 部署宝塔面板实操
  • Arduino UNO R3自学笔记23 之 Arduino如何使用4511控制数码管?
  • 【多重循环在Java中的应用】
  • ES postman操作全量修改,局部修改,删除
  • 今日份总结
  • 机器学习-支撑向量机SVM
  • 【基于YOLOv5的反光衣检测预警系统】可检测图片、视频、摄像头,支持GPU加速检测以及语音播报预警
  • Promise 的描述
  • pg if条件语句
  • Python爬虫之正则表达式于xpath的使用教学及案例
  • 合约测试用例详解