首页 > 其他分享 >Cannon-es.js之Distance Constrait模拟布料

Cannon-es.js之Distance Constrait模拟布料

时间:2024-09-30 23:23:23浏览次数:9  
标签:Constrait Distance const Cannon THREE let 模拟 new es

本文目录

前言

在现代Web开发中,实现逼真的物理效果对于提升用户体验至关重要。Cannon-es.js,作为Cannon.jsES6模块版本,凭借其轻量级、高性能和易于集成的特点,在WebGL环境中进行物理模拟时备受青睐。本文将深入探讨Cannon-es.js在模拟物理效果方面的应用,包括Particle(粒子)的基本使用、前置代码准备,以及如何使用距离约束来模拟布料效果。
粒子系统在游戏开发、动画制作以及物理模拟等领域有着广泛的应用。通过Cannon-es.js,我们可以轻松创建和管理粒子,实现各种复杂的物理效果。此外,距离约束作为一种强大的物理约束类型,允许我们模拟物体之间的连接关系,这在模拟布料、绳索等柔性物体时尤为有用。
在接下来的内容中,我们将详细介绍如何准备前置代码,如何使用Cannon-es.js创建粒子,并通过距离约束来模拟布料效果。希望通过本文的探讨,读者能够掌握Cannon-es.js在物理模拟方面的基本技巧,并在自己的项目中实现更加复杂和逼真的物理效果。

最终效果

请添加图片描述

1、Particle

cannon-es(一个轻量级的JavaScript物理引擎,用于处理刚体动力学模拟)中,Particle(粒子)并不是传统意义上的三维几何体(如球体、立方体等),而是一个没有形状、大小或旋转属性的质量点。粒子主要用于模拟点质量的行为,如重力作用下的自由落体、碰撞检测中的接触点,或者作为更复杂刚体的一部分(例如,通过约束将多个粒子连接在一起以形成软体物理效果)。
Particlecannon-es中是一个特殊的Body类型,它只具有位置(position)、速度(velocity)和力(force)等属性,而没有形状(shape)和惯性(inertia)等刚体通常具有的属性。由于粒子没有形状,因此它们不会直接参与碰撞检测中的边界计算;相反,它们通常通过与其他粒子或刚体的接触点来间接参与碰撞。
cannon-es中创建一个Particle通常涉及以下步骤:

  1. 创建一个CANNON.Body实例,但将其形状(shape)属性设置为null或省略(因为粒子没有形状)。
  2. 设置粒子的质量(mass)。
  3. (可选)设置粒子的初始位置(position)和速度(velocity)。

2、前置代码准备

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 rows = 15
    const cols = 15
    const sphereGeometry = new THREE.SphereGeometry(0.2, 16, 16)
    const sphereMaterial = new THREE.MeshBasicMaterial({color: 0xff0000})
    const particleShape = new CANNON.Particle()
    let bodies = {}
    for(let i = 0; i < cols; i++) {
       for(let j = 0; j < rows; j++) {
        // 物理世界
        const particleBody = new CANNON.Body({
            mass: 0.5,
            position: new CANNON.Vec3(i - cols * 0.5, 10, j - rows * 0.5),
            shape: particleShape
        })
        bodies[`${i}-${j}`] = particleBody
        physicsWorld.addBody(particleBody)
        phyMeshes.push(particleBody)

        // 渲染世界
        const sphereMesh = new THREE.Mesh(sphereGeometry, sphereMaterial)
        sphereMesh.position.set(i - cols * 0.5, 10, j - rows * 0.5)
        meshes.push(sphereMesh)
        scene.add(sphereMesh)
       }
    }
    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.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 代码

在上面的基础添加距离约束代码:

    for(let i = 0; i < cols; i++) {
        for(let j = 0; j < rows; j++) {
            const body = bodies[`${i}-${j}`]
            if (i > 0) {
                const body2 = bodies[`${i - 1}-${j}`]
                const constraint = new CANNON.DistanceConstraint(body, body2, 0.4)
                physicsWorld.addConstraint(constraint)
            }
            if (j > 0) {
                const body2 = bodies[`${i}-${j - 1}`]
                const constraint = new CANNON.DistanceConstraint(body, body2, 0.4)
                physicsWorld.addConstraint(constraint)
            }
        }
    }

3.2 效果

请添加图片描述

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

标签:Constrait,Distance,const,Cannon,THREE,let,模拟,new,es
From: https://blog.csdn.net/weixin_44103733/article/details/142655300

相关文章

  • CS 168 Distance-Vector Routing
    CS168Fall2024Project 2:Distance-Vector RoutingInthis project,youwillwriteadistance-vectorroutingprotocol.We have provided simulatorcodethatyoucanusetovisualizeyour protocol in action.Lecturesneededforthisproject:Lecture6(Rou......
  • C# 在给定斜率的线上找到给定距离处的点(Find points at a given distance on a line o
     给定二维点p(x0,y0)的坐标。找到距离该点L的点,使得连接这些点所形成的线的斜率为M。例子: 输入:p=(2,1)    L=sqrt(2)    M=1输出:3,2    1,0解释:与源的距离为sqrt(2),并具有所需的斜率m=1。输入:p=(1,0)   ......
  • Hausdorff Distance 和 Euclidean Distance Mean欧氏距离
    importtorchimporttorch.nnasnnclassHausdorffDistanceLoss(nn.Module):def__init__(self):super(HausdorffDistanceLoss,self).__init__()defforward(self,pred,target):#扩展为(B,N,1,D)和(B,1,M,D)pred=pred......
  • TCPIP路由技术第一卷 第三大部分-7 策略路由、distance、环路
    r1:routerospf110redripsubnetstag100route-maptagmatchipadd10routerospf110redripsubnetsroute-maptagroute-maptagsettag114access-list10permit33.1.1.00.0.0.255r4:access-list10permit33.1.1.00.0.0.255route-maptmatchipad......
  • 汉明距离(Hamming distance)
    在图像信号处理中,汉明距离(Hammingdistance)通常用于比较两个图像之间的差异程度。汉明距离原本是衡量两个等长字符串之间对应位置上不同字符的数量,但在图像处理中,它也可以用来比较两个图像的像素值差异。计算步骤1、图像预处理:确保两个图像的尺寸相同,如果不同,则需要通过缩放或......
  • Codeforces Round 903 (Div. 3) F. Minimum Maximum Distance
    https://codeforces.com/contest/1881/problem/F不难发现一件事情,我们这里最后的答案所在的点是1和3号点。我们有没有发现一个性质:就是这两个点都是红点间的路径上的,而且最后的答案就是最长的红点间的距离的长度除以二上取整。那么,我们怎么找到最长的红点间的距离呢?很显......
  • ABC201E Xor Distances 题解
    ABC201EXorDistances题解题目大意给定一个带权树,求树上每两点的简单路径上的边权的异或和的和。形式化的,定义\(dis(i,j)\)为\(i\)到\(j\)的简单路径上的边权的异或和,求\(\large\sum\limits_{i=1}^n\sum\limits_{j=i+1}^n\text{dis}(i,j)\)。Solve令\(\largef(u)=......
  • 论文笔记:Investigation of Passengers’ Perceived Transfer Distance in Urban Rail
    (基于XGBoost和SHAP的城市轨道交通站点乘客感知换乘距离研究)话题点:城市轨道交通站点、换乘距离、XGBoost模型、SHAP模型:感知传输距离偏差theRatioofPerceivedTransferDistanceDeviation(R)、XGBoost和SHAP模型考虑的因素:乘客个人属性、换乘设施和换乘环境相关的32个指......
  • Distance to Different
    最开始观察\(a\)没看出什么东西来,于是看\(b\),由于统计的是不同的\(b\)的数量,所以考虑一个\(b\)可以由什么\(a\)搞出来,然后就不难发现如果我们将\(a\)分段(相同的数放一段),那么对应的\(b\)在同一段就会从\(1\)开始增加,然后到达一个峰值之后再减小到\(1\)(开头和结尾的两段只有减少或增......
  • Leetcode 3244. Shortest Distance After Road Addition Queries II
    Leetcode3244.ShortestDistanceAfterRoadAdditionQueriesII1.解题思路2.代码实现题目链接:3244.ShortestDistanceAfterRoadAdditionQueriesII1.解题思路这一题的话由于题目限制了road不会交叉,因此我们只需要在每次增加road之后将中间节点删除,剩余的路......