Cannon-es物理引擎中物体动力控制的深度探索

news2024/12/25 23:54:06

本文目录

  • 前言
  • 1、cannon-es给物体施加力
    • 1.1 前置代码
    • 1.2 效果
    • 1.3 给小球施加力
      • 1. applyForce
        • 效果
      • 2. applyImpulse
        • 效果
      • 3. applyLocalImpulse
        • 效果
      • 4. applyTorque
        • 效果
      • 区别总结

前言

在三维物理引擎的世界里,Cannon-ES以其轻量级和高效能著称,为开发者提供了强大的工具来模拟现实世界中的物理现象。本指南将带您深入探索Cannon-ES中如何给物体施加不同类型的力,从而控制其动态行为。从基础的applyForce到瞬间的applyImpulse,再到局部坐标系下的applyLocalImpulse,以及改变物体旋转的applyTorque,我们将逐一解析这些方法的用法、效果及其之间的区别。
通过前置代码的搭建,您将能够快速上手并理解每个方法的基本使用方式。随后,我们将通过实际示例展示如何给小球施加不同类型的力,并观察其产生的不同效果。这不仅能帮助您理解物理引擎背后的原理,还能激发您在游戏开发、物理模拟等领域的创造力。
让我们一同踏上这段探索之旅,掌握Cannon-ES中物体动力控制的精髓,为您的项目增添更多生动与真实感。

1、cannon-es给物体施加力

1.1 前置代码

<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.offsetWidth
    const 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, 30)
    // 创建渲染器
    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 groundMaterial = new CANNON.Material('groundMaterial')
    groundMaterial.friction = 1
    groundMaterial.restitution = 1 // 反弹系数

    const planeShape = new CANNON.Plane()

    // 创建物理地面
    const groundBody = new CANNON.Body({
        mass: 0, // 为0表示地面不受重力影响
        shape: planeShape,
        position: new CANNON.Vec3(0, 0, 0),
        material: groundMaterial,
    })
    groundBody.quaternion.setFromEuler(-Math.PI / 2, 0, 0)
    physicsWorld.addBody(groundBody)

    // 设置球体材质
    const sphereMaterial = new CANNON.Material('sphereMaterial')
    sphereMaterial.friction = 0 // 摩擦系数
    sphereMaterial.restitution = 0 // 反弹系数

    // 创建球体刚体
    const sphereShape = new CANNON.Sphere(1) // 创建球体形状,并且传递半径跟threejs中的小球半径一致
    const sphereBody = new CANNON.Body({
        mass: 1,
        position: new CANNON.Vec3(0, 1, 0),
        material: sphereMaterial,
        shape: sphereShape
    })

    physicsWorld.addBody(sphereBody)
    phyMeshes.push(sphereBody)
    // 物理世界结束

    // 场景世界开始
    const axesHelper = new THREE.AxesHelper( 15 );
    scene.add( axesHelper );
    // 地面
    const plane = new THREE.Mesh(
        new THREE.PlaneGeometry(30, 30),
        new THREE.MeshBasicMaterial({
            wireframe: true
        })
    )
    plane.rotation.x = -Math.PI/2
    // 添加到场景中
    scene.add(plane)
    // 小球 
    const sphere = new THREE.Mesh(
        new THREE.SphereGeometry(1, 20, 10),
        new THREE.MeshBasicMaterial({ 
            color: 0xff0000,
            wireframe: true
        })
    )
    scene.add(sphere)
    meshes.push(sphere)
    // 场景世界结束 

    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.05
    control.enableDamping = true

    // 渲染循环动画
    function animate() {
        // 在这里我们创建了一个使渲染器能够在每次屏幕刷新时对场景进行绘制的循环(在大多数屏幕上,刷新率一般是60次/秒)
        requestAnimationFrame(animate)
        updatePhysic()
        // 更新控制器。如果没在动画里加上,那必须在摄像机的变换发生任何手动改变后调用
        control.update()
        renderer.render(scene, camera)
    }

    // 执行动画
    animate()
})
</script>
<style scoped>
.cannonDemo {
    width: 100vw;
    height: 100vh;
}
</style>

1.2 效果

请添加图片描述
可以看到我们的场景中有一个线框小球。

1.3 给小球施加力

在cannon-es这个3D物理引擎中,applyForce、applyImpulse、applyLocalImpulse和applyTorque是用于控制刚体动态行为的重要方法。它们各自具有不同的用途、参数使用方式和效果。以下是这四个方法的详细解释、区别以及参数使用方法的说明:

1. applyForce

  • 作用applyForce方法用于在刚体上施加一个持续的力。这个力会按照物理学的原理(F=ma)逐渐改变刚体的速度和运动状态。

  • 参数

    • force:一个CANNON.Vec3向量,表示要施加的力的大小和方向。
    • worldPoint(可选):一个CANNON.Vec3向量,表示力作用在刚体上的世界坐标系中的点。如果不提供此参数,则默认作用在刚体的质心上。
  • 使用示例

      const force = new CANNON.Vec3(50, 0, 0); // 在X轴上施加一个100单位的力
      sphereBody.applyForce(force, new CANNON.Vec3(0, -1, 0)); // 将力作用在刚体的当前位置
    

    力作用在小球的正中心底部,它就会形成回旋向前进

    效果

    请添加图片描述

2. applyImpulse

  • 作用applyImpulse方法用于在刚体上施加一个瞬间的冲量。这个冲量会直接影响刚体的速度,使其立即获得一个速度增量。
  • 参数
    • impulse:一个CANNON.Vec3向量,表示要施加的冲量的大小和方向。
    • worldPoint(可选):与applyForce相同,表示冲量作用在刚体上的世界坐标系中的点。
  • 使用示例
      const impulse = new CANNON.Vec3(5, 0, 0); // 在x轴上施加一个5单位的冲量
      sphereBody.applyImpulse(impulse, sphereBody.position); // 将冲量作用在刚体的当前位置
    
    效果
    请添加图片描述

3. applyLocalImpulse

  • 作用applyLocalImpulse方法与applyImpulse类似,也是用于施加瞬间的冲量,但不同之处在于它接受的是局部坐标系下的冲量向量。
  • 参数
    • localImpulse:一个CANNON.Vec3向量,表示在刚体局部坐标系中要施加的冲量的大小和方向。
    • localPoint(可选):一个CANNON.Vec3向量,表示冲量作用在刚体上的局部坐标系中的点。如果不提供此参数,则默认作用在刚体的局部质心上。
  • 使用示例
        const localImpulse = new CANNON.Vec3(0, 0, 9); // 在刚体局部坐标系的Z轴上施加一个9单位的冲量
      sphereBody.applyLocalImpulse(localImpulse, new CANNON.Vec3()); // 默认作用在局部质心上
    
    效果
    请添加图片描述

4. applyTorque

  • 作用applyTorque方法用于在刚体上施加一个力矩,使其产生旋转。这个力矩会改变刚体的角速度和旋转方向。
  • 参数
    • torqueCANNON.Vec3,表示要施加的力矩的大小和方向。力矩的方向遵循右手定则,即右手四指从力矩的起点指向终点,大拇指的方向即为力矩的旋转方向。
  • 使用示例
      const torque = new CANNON.Vec3(0, 0, 100); // 在Z轴上施加一个使刚体绕Z轴旋转的力矩
      sphereBody.applyTorque(torque); // 施加力矩
    
    效果
    请添加图片描述

区别总结

方法作用特点参数
applyForce施加持续的力渐进改变速度force(必需),worldPoint(可选)
applyImpulse施加瞬间的冲量立即改变速度impulse(必需),worldPoint(可选)
applyLocalImpulse施加瞬间的冲量(局部坐标系)立即改变速度,冲量在局部坐标系中定义localImpulse(必需),localPoint(可选)
applyTorque施加力矩改变角速度和旋转方向torque(必需)

在使用这些方法时,需要注意以下几点:

  • 力的方向和大小、冲量的大小和方向、力矩的大小和方向都是通过CANNON.Vec3向量来指定的,该向量包含X、Y、Z三个分量。
  • 力的作用点和冲量的作用点可以是刚体上的任意点,但如果不指定,则默认作用在刚体的质心上。对于力矩,它总是绕刚体的质心旋转,因为力矩的作用点默认是质心。
  • 施加力、冲量或力矩后,刚体的运动状态会相应地发生变化,包括速度、角速度等。
  • 在使用applyLocalImpulse时,需要确保提供的冲量向量是在刚体的局部坐标系中定义的。如果刚体发生了旋转,那么局部坐标系也会随之变化。

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2167667.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

寿司检测系统源码分享

寿司检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vision …

zabbix“专家坐诊”第257期问答

问题一 Q&#xff1a;zabbix5.0监控项里的键值&#xff0c;怎么设置变量值&#xff1f;{#ABC} {$ABC} 都识别不到变量。 A&#xff1a;可以参考一下这个。 问题二 Q&#xff1a;我想问一下用odbc创建监控项&#xff0c;生成了json格式&#xff0c;如何创建一个触发器去判断里面…

精准控制交易亏损:掌握关键止损点设置技巧

前段时间&#xff0c;咱们探讨了开仓的策略&#xff0c;那今天就需要来聊聊止损的技巧了。一个好的开始很重要&#xff0c;但知道何时止损也是同样关键。市场波动大&#xff0c;机会稍纵即逝。当趋势变得不明确时&#xff0c;止损可以帮助我们管理风险&#xff0c;防止损失加剧…

Spring Cloud Gateway 之动态uri 自定义过滤器

背景&#xff1a;第三方公司 请求本公司入参和出参一样的同一个接口&#xff0c;根据业务类型不一样需要不同业务微服务处理 &#xff0c;和第三方公司协商在请求头中加入业务类型方便我公司在网关成分发请求。 1&#xff1a;在spring cloud gateway yml 中加入路由 重点是 -…

STL——map和set【map和set的介绍和使用】【multimap和multiset】

目录 map和set1.关联式容器2.键值对3.树形结构的关联式容器3.1set3.1.1set的介绍3.1.2set的使用3.1.2.1set的模版参数列表3.1.2.2set的构造3.1.2.3set的迭代器3.1.2.4set基本接口的使用3.1.2.5set使用案例 3.2map3.2.1map介绍3.2.2map的使用3.2.2.1map的构造3.2.2.2map的迭代器…

一个必会算法模型,XGBoost !!

大家好&#xff0c;今天咱们来聊聊XGBoost ~ XGBoost&#xff08;Extreme Gradient Boosting&#xff09;是一种集成学习算法&#xff0c;是梯度提升树的一种改进。它通过结合多个弱学习器&#xff08;通常是决策树&#xff09;来构建一个强大的集成模型。 XGBoost 的核心原理…

数据结构练习题————(二叉树)——考前必备合集!

今天在牛客网和力扣上带来了数据结构中二叉树的进阶练习题 1.二叉搜索树与双向链表———二叉搜索树与双向链表_牛客题霸_牛客网 (nowcoder.com) 2.二叉树遍历————二叉树遍历_牛客题霸_牛客网 (nowcoder.com) 3.二叉树的层序遍历————102. 二叉树的层序遍历 - 力扣&am…

C# 一键清空控件值

_场景&#xff1a;_在任何一个Form表单的操作页面或者数据台账的查询页面&#xff0c;基本都会看到一个清除的按钮&#xff0c;其功能就是用来清除我们需要抛弃的已经写入到控件内的数据。如果一个个控件来处理的话&#xff0c;想必会非常麻烦&#xff0c;而且系统不单单只是一…

杭州算力小镇:AI泛化解锁新机遇,探寻AI Agent 迭代新路径

人工智能技术不断迭代&#xff0c;重点围绕着两个事情&#xff0c;一是数据&#xff0c;二是算力。 算法的迭代推动着AI朝向多模态的方向发展&#xff0c;使之能够灵活应对不同领域的不同任务&#xff0c;模型的任务执行能力大大提升&#xff0c;人工智能泛化能力被推上高潮。…

scala 2.12 error: value foreach is not a member of Object

如图所示&#xff1a;在scala 2.11的时候下面的不报错&#xff0c;但是在2.12下报错了 在scala2.12环境下错误如下&#xff1a; 经过查找资料得到&#xff1a;df 后面加上rdd 即可

kafka下载配置

下载安装 参开kafka社区 zookeeperkafka消息队列群集部署https://apache.csdn.net/66c958fb10164416336632c3.html 下载 kafka_2.12-3.2.0安装包快速下载地址分享 官网下载链接地址&#xff1a; 官网下载地址&#xff1a;https://kafka.apache.org/downloads 官网呢下载慢…

详细解读,F5服务器负载均衡的技术优势

在现代大规模、高流量的网络使用场景中&#xff0c;为应对高并发和海量数据的挑战&#xff0c;服务器负载均衡技术应运而生。但凡知道服务器负载均衡这一名词的&#xff0c;基本都对F5有所耳闻&#xff0c;因为负载均衡正是F5的代表作&#xff0c;换句通俗易懂的话来说&#xf…

需求: 通过后台生成的树形结构,返回给前台用于动态生成表格标题,并将对应标题下面的信息对应起来

1. 如图所以&#xff0c;完成以下内容对应 2. 代码示例如下&#xff0c; 动态生成树形结构列名称&#xff0c;并将表格中存在的值与其对应起来 /*** 查询资源计划列表** param resourcePlan 资源计划* return 资源计划*/Overridepublic Map<String, Object> selectResour…

程序编译的四个阶段

程序编译的四个阶段 #include <stdio.h>int main(){printf("Hello World~");return 0; } hello.c程序的生命周期从一个高级C语言程序开始&#xff0c;这种形式容易被人读懂。 但这无法直接被计算机读懂。为了在系统上运行hello.c程序&#xff0c;每条C语言都…

科研绘图系列:R语言组合多个图形

文章目录 介绍加载R包画图介绍 通过patchworkR包组合多个ggplot数据图形对象。 加载R包 library(ggplot2) library(patchwork)画图 画图theme_set(theme_bw() +theme(

2024年408真题计算机网络篇

1 https://zhuanlan.zhihu.com/p/721169467。最小割可以看作是切断水流的最薄弱环节——通过切断这些关键的“水管”&#xff0c;就可以完全阻止水从源点流到汇点。 在下列二进制数字调制方法中&#xff0c;需要2个不同频率载波 的是 A. ASK B. PSK C. FSK D. DPSK 解答…

Linux终端简介

Linux终端简介 导语基本终端交互终端读写标准/非标准模式重定向处理 终端对话 termios结构模式相关输入模式输出模式控制模式本地模式特殊控制字符终端速度其他函数 终端输出终端类型terminfo 击键动作检测虚拟控制台&伪终端总结参考文献 导语 本章基本是以一个简单的用户…

PlayerPerfs-不同平台的存储位置

一 .PlayerPrefs存储的数据存在哪里 不同平台存储位置不一样 Windows PlayerPrefs 存储在 HKCU\Software\[公司名称]\[产品名称] 项下的注册表中 其中公司和产品名称是 在“Project Settings”中设置的名称。 查看方法&#xff1a; 运行 regedit HKEY…

手游和应用出海资讯:三七新游首月收入突破700万元;领英尝试推出游戏功能以增加用户使用时长

NetMarvel帮助游戏和应用广告主洞察全球市场、获取行业信息&#xff0c;以下为9月第四周资讯&#xff1a; ● 《AFK Journey》收入突破 1.5 亿美元 ● 《黑神话&#xff1a;悟空》IGN年度游戏投票第一掉至第三 ● 三七发布新游首月收入突破700万元 ● 开罗游戏《哆啦A梦的铜锣烧…

Ubuntu22.04安装paddle

查看系统版本信息 使用命令lsb_release -a查看系统版本 rootLAIS01:~# lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 22.04.5 LTS Release: 22.04 Codename: jammy查看系统支持的cuda版本&#xff0c;使用命令nvidia-smi&#…