Cannon-es.js之Distance Constrait物体约束详解

news2024/12/27 3:29:40

本文目录

  • 前言
  • 最终效果
  • 1、Distance Constrait的基本属性和方法
    • 1.1 属性
    • 1.2 方法
  • 2、Distance Constrait的约束详解
    • 2.1 前置代码准备
    • 2.2 效果
  • 3、模拟生成小球撞击
    • 3.1 代码
    • 3.2 效果

前言

在Cannon-es.js中,DistanceConstraint(距离约束)是一种用于在物理引擎中约束两个刚体之间距离的约束类型。这种约束确保了无论这两个刚体如何移动,它们之间的相对距离都保持不变或者保持在一个指定的范围内。以下是关于DistanceConstraint的详细介绍,包括其属性和方法。

最终效果

请添加图片描述

1、Distance Constrait的基本属性和方法

1.1 属性

DistanceConstraint的主要属性:

  • bodyA:第一个被约束的刚体。在创建DistanceConstraint时,需要知道这个刚体
  • bodyB:第二个被约束的刚体。同样,在创建DistanceConstraint时,也需要指定这个刚体。
  • distance:要保持的距离。这是两个刚体之间应当保持的恒定距离。如果为定义,它将被设置为刚体A和刚体B之间的当前距离。
  • maxForce:约束物体应施加的最大力。这是当试图维持制定距离时,约束可以施加在刚体上的最大力量。它有助于防止因约束而导致的刚体行为过于极端。

1.2 方法

虽然DistanceConstraint在Cannon-es.js中可能没有直接暴露太多的方法供调用(因为约束的主要逻辑是内嵌在物理引擎中的),但通常会有一些通用的方法来管理约束,如:

  1. 启用/禁用:虽然Cannon-es.js可能不直接提供enable或disable方法来针对DistanceConstraint启用或禁用约束,但可以通过将约束从物理世界中移除(通过调用world.removeConstraint(constraint))来间接禁用它,或者通过重新添加到物理世界中来启用它。

2、Distance Constrait的约束详解

2.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, 70)
    // 创建渲染器
    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 = 0 // 反弹系数

    // 创建物理地面
    const groundBody = new CANNON.Body({
        mass: 0, // 为0表示地面不受重力影响
        shape: new CANNON.Box(new CANNON.Vec3(20, 0.05, 20)),
        position: new CANNON.Vec3(0, 0, 0),
        material: groundMaterial,
    })
    physicsWorld.addBody(groundBody)

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


    const sphereThreeGeometry = new THREE.SphereGeometry( 1, 32, 16 )
    const sphereThreeMaterial = new THREE.MeshBasicMaterial({
        color: 0xff0000,
    })
    const sphereShape = new CANNON.Sphere(1)
    let previousBody
    for (let i = 0; i < 9; i++) {
        // 场景世界 创建一个球立方体
        const sphereThreeMesh = new THREE.Mesh(
            sphereThreeGeometry,
            sphereThreeMaterial
        )
        meshes.push(sphereThreeMesh)
        scene.add(sphereThreeMesh)

        // 物理世界 创建球刚体
        const sphereBody = new CANNON.Body({
            mass: i == 0 ? 0 : 1,
            position: new CANNON.Vec3(0, 25 - i * 2.2, 0),
            material: sphereMaterial,
            shape: sphereShape,
            type: i == 0 ? CANNON.Body.STATIC : CANNON.Body.DYNAMIC
        })

        physicsWorld.addBody(sphereBody)
        phyMeshes.push(sphereBody)

        if (i > 0) {
            const constraint = new CANNON.DistanceConstraint(
                previousBody,
                sphereBody,
                2.2
            )
            physicsWorld.addConstraint(constraint)
        }
        previousBody = sphereBody
    }



    // 场景世界开始
    const axesHelper = new THREE.AxesHelper(30);
    scene.add(axesHelper);
    // 地面
    const plane = new THREE.Mesh(
        new THREE.BoxGeometry(40, 0.1, 40),
        new THREE.MeshBasicMaterial({
            wireframe: true
        })
    )
    // 添加到场景中
    scene.add(plane)
    // 场景世界结束 

    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>

2.2 效果

在这里插入图片描述


3、模拟生成小球撞击

3.1 代码

代码:

window.addEventListener('click', () => {
        // three.js
        const geometry = new THREE.SphereGeometry(1, 32, 16)
        const material = new THREE.MeshBasicMaterial({ color: 0xffff00 })
        const sphere = new THREE.Mesh(geometry, material)
        scene.add(sphere)
        meshes.push(sphere)

        // cannon-es.js
        const sphereBody = new CANNON.Body({
            mass: 1,
            shape: new CANNON.Sphere(1),
            position: new CANNON.Vec3(0, 18, 5), // 初始位置  
            velocity: new CANNON.Vec3(0,0,-10), // 初始速度  
        });
        phyMeshes.push(sphereBody)
        physicsWorld.addBody(sphereBody)
    })

3.2 效果

请添加图片描述

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

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

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

相关文章

【华为HCIP实战课程三】动态路由OSPF的NBMA环境建立邻居及排错,网络工程师

一、NBMA环境下的OSPF邻居建立问题 上节我们介绍了NBMA环境下OSPF邻居建立需要手动指定邻居,因为NBMA环境是不支持广播/组播的 上一节AR1的配置: ospf 1 peer 10.1.1.4 //手动指定邻居的接口地址,而不是RID peer 10.1.1.5 area 0.0.0.0 手动指定OSPF邻居后抓包查看OSP…

Linux命令:块设备信息查看命令lsblk的具体介绍

目录 一.lsblk的介绍 二.基础用法 2.1基础命令和示意图 2.2详细说明 三.进阶用法 3.1列出指定的块设备信息 3.2查看设备完整路径 3.3强制以树形式输出信息 3.4其他参数 一.lsblk的介绍 lsblk是Linux系统中的一个命令行工具&#xff0c;用于列出所有可用的块设备&#…

基于单片机的可调式中文电子日历系统

** 文章目录 前言概要功能设计软件设计效果图 程序文章目录 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师&#xff0c;一名热衷于单片机技术探索与分享的博主、专注于 精通51/STM32/MSP430/AVR等单片机设计 主要对象是咱们…

RK3588主板PCB设计学习(六)

可以在其它层对过孔进行削盘处理&#xff0c; 可以看到&#xff0c;这里有些过孔用不上&#xff0c;在这一层进行了削盘处理&#xff1a; 对于这种电源层进行铺铜操作的时候&#xff0c;如果不进行削盘处理的话这些焊盘可能导致这个电源层面不完整&#xff0c;存在割裂的风险&a…

平安养老险肇庆中心支公司开展“2024年金融教育宣传月”活动

为加强消费者金融教育宣传&#xff0c;切实提升社会公众金融素养&#xff0c;有效防范化解金融风险&#xff0c;营造和谐健康金融环境&#xff0c;在肇庆金融监管分局指导下&#xff0c;平安养老险肇庆中心支公司开展金融教育宣传月暨反洗钱宣传月系列活动。 9月11日&#xff…

基于Springboot+Vue的高校教室资源管理系统的设计与实现(含源码+数据库)

1.开发环境 开发系统:Windows10/11 架构模式:MVC/前后端分离 JDK版本: Java JDK1.8 开发工具:IDEA 数据库版本: mysql5.7或8.0 数据库可视化工具: navicat 服务器: SpringBoot自带 apache tomcat 主要技术: Java,Springboot,mybatis,mysql,vue 2.视频演示地址 3.功能 这个系…

学习docker第二弹------基本命令[帮助启动类命令、镜像命令、容器命令]

docker目录 前言基本命令帮助启动类命令停止docker服务查看docker状态启动docker重启docker开机启动docker查看概要信息查看总体帮助文档查看命令帮助文档 镜像命令查看所有的镜像 -a查看镜像ID -q在仓库里面查找redis拉取镜像查看容器/镜像/数据卷所占内存删除一个镜像删除多个…

美图AI短片创作工具MOKI全面开放 支持生成配乐、细节修改

人工智能 - Ai工具集 - 集合全球ai人工智能软件的工具箱网站 美图公司近日宣布&#xff0c;其研发的AI短片创作工具MOKI已正式向所有用户开放。这款专注于AI短片创作的工具&#xff0c;提供了包括动画短片、网文短剧等多种类型视频内容的生成能力&#xff0c;致力于为用户带来…

Foo a30 = Foo(123);会调用哪些构造函数

一、解答 在您提供的代码中&#xff0c;表达式 Foo a30 Foo(123); 会直接调用 Foo 类中接受一个 int 类型参数的构造函数。这里是构造函数的调用过程&#xff1a; Foo(123) 创建了一个临时的 Foo 对象&#xff0c;使用的是接受 int 参数的构造函数。这个构造函数内部会执行 c…

6.数据结构与算法-线性表的链式表示和实现-单链表

链式存储结构 与链式存储有关的术语 单链表&#xff0c;双链表&#xff0c;循环链表 头指针&#xff0c;头节点&#xff0c;首元节点 有无头节点的区别 如何表示空表 设置头节点的好处 头节点的数据域内装什么 链表&#xff08;链式存储&#xff09;的特点 带头节点的单链表 单…

【中级通信工程师】综合能力:2024年真题回顾(附答案)

【零基础3天通关中级通信工程师】 综合能力&#xff1a;2024年真题回顾 本文是根据参加考试的回忆并且结合网上几版资料复原的2024年通信考试中级《综合能力》的真题考卷&#xff0c;旨在为广大考生提供复习和备考的参考&#xff0c;试卷大体和真题相符&#xff0c;部分选项回…

算法闭关修炼百题计划(一)

多看优秀的代码一定没有错&#xff0c;此篇博客属于个人学习记录 1.两数之和2.前k个高频元素3.只出现一次的数字4.数组的度5.最佳观光组合6.整数反转7.缺失的第一个正数8.字符串中最多数目的子序列9.k个一组翻转链表10.反转链表II11. 公司命名12.合并区间13.快速排序14.数字中的…

Windows Defender 强力删除工具 Defender Remover 下载

DefenderRemover.exe官方版下载丨最新版下载丨绿色版下载丨APP下载-123云盘123云盘为您提供DefenderRemover.exe最新版正式版官方版绿色版下载,DefenderRemover.exe安卓版手机版apk免费下载安装到手机,支持电脑端一键快捷安装https://www.123865.com/s/ajCgTd-79HEDefenderRemo…

文件传输工具 | 闪电藤 v2.5.5 绿色版

软件简介 闪电藤是一款基于LocalSend二次开发的局域网文件传输工具。它特别针对中国用户的使用习惯&#xff0c;对UI交互进行了重新设计&#xff0c;并在功能上进行了增强和删减。这款工具的特点包括极简无广告的界面&#xff0c;无需登录即可使用&#xff0c;能够自动连接同一…

一钉多用:自攻螺钉在家居与工业领域的广泛应用

自攻螺钉的结构要素有哪些重要特点&#xff1f; 自攻螺钉适用于非金属或软金属&#xff0c;不需要配合预先开好的孔和攻牙。自攻螺钉的尖头设计使其能够“自我攻入”材料中&#xff1b;而普通螺丝通常是平头&#xff0c;规格一致。自攻螺钉的关键在于&#xff0c;打孔时不需要进…

Java五子棋

目录 一&#xff1a;案例要求&#xff1a; 二&#xff1a;代码&#xff1a; 三&#xff1a;结果&#xff1a; 一&#xff1a;案例要求&#xff1a; 实现一个控制台下五子棋的程序。用一个二维数组模拟一个15*15路的五子棋棋盘&#xff0c;把每个元素赋值位“┼”可以画出棋…

猴子都看不懂的矩阵乘法——由向量乘矩阵到矩阵乘矩阵

矩阵乘法 仅为初学者的理解&#xff0c;不喜勿喷 矩阵&#xff0c;即为如下形式的结构&#xff1a; 0 1 1 1 1 0 1 0 1 \begin{matrix} 0&1&1\\ 1&1&0\\ 1&0&1\\ \end{matrix} 011​110​101​ 既然你准备仔细阅读这篇文章&#xff0c;那么相信你应…

5个你一定要知道的Word使用小技巧

在职场中&#xff0c;Microsoft Word已经成为我们日常工作中必不可少的工具。无论是制作报告、文档还是演示文稿&#xff0c;Word都扮演着重要的角色。 许多人已经掌握了Word使用小技巧&#xff0c;今天小编给大家整理了Word表格小技巧&#xff0c;这5个你一定要知道哦&#xf…

软考论文《论NoSQL数据库技术及其应用》精选试读

论文真题 随着互联网web2.0网站的兴起&#xff0c;传统关系数据库在应对web2.0 网站&#xff0c;特别是超大规模和高并发的web2.0纯动态SNS网站上已经显得力不从心&#xff0c;暴露了很多难以克服的问题&#xff0c;而非关系型的数据库则由于其本身的特点得到了非常迅速的发展…

Linux防火墙-nat表

作者介绍&#xff1a;简历上没有一个精通的运维工程师。希望大家多多关注作者&#xff0c;下面的思维导图也是预计更新的内容和当前进度(不定时更新)。 我们经过上小章节讲了Linux的部分进阶命令&#xff0c;我们接下来一章节来讲讲Linux防火墙。由于目前以云服务器为主&#x…