您的位置:首页 > 文旅 > 旅游 > 耐看舒适的网页设计欣赏_太原百度网站快速优化_网络营销推广网站_百度经验官网登录

耐看舒适的网页设计欣赏_太原百度网站快速优化_网络营销推广网站_百度经验官网登录

2024/10/7 10:13:40 来源:https://blog.csdn.net/weixin_44103733/article/details/142670533  浏览:    关键词:耐看舒适的网页设计欣赏_太原百度网站快速优化_网络营销推广网站_百度经验官网登录
耐看舒适的网页设计欣赏_太原百度网站快速优化_网络营销推广网站_百度经验官网登录

本文目录

  • 前言
  • 最终效果
  • 1、postStep
  • 2、前置准备
    • 2.1 代码
    • 2.2 效果
  • 3、removeConstraint
    • 3.1 解除约束代码
    • 效果
  • 4、完整代码

前言

在3D物理引擎的广阔天地中,cannon-es以其轻量级、高性能和易于集成的特点,成为了WebGL环境中物理模拟的首选工具。它不仅能够精准地模拟刚体碰撞、力学行为和约束等物理现象,还提供了丰富的API供开发者自由调用。
本文将深入探讨cannon-es中的两个关键特性:postStep事件(尽管cannon-es官方文档中可能并未直接提及,但我们可以基于物理引擎的通用概念进行阐述)和removeConstraint方法。postStep通常被理解为在物理模拟步骤之后执行的操作,它允许开发者在物理世界更新后插入自定义逻辑。而removeConstraint方法则是用来从物理世界中移除不再需要的约束,从而优化模拟性能和准确性。
接下来,我们将通过前置代码准备、解除约束的代码示例及其效果展示,以及完整的代码汇总,来详细解析这两个特性的实际应用。无论你是物理引擎的新手,还是经验丰富的开发者,本文都将为你提供一份详尽的指南,帮助你更好地掌握cannon-es的精髓。

最终效果

请添加图片描述

1、postStep

Cannon-es.js作为Cannon.js的现代分支,是一款专为WebGL设计的轻量级、高性能3D物理引擎,能够轻松模拟真实世界中的物理现象,如刚体碰撞、力学模拟和约束等。在物理引擎中,模拟步骤之后执行一些额外的逻辑,比如更新渲染场景、处理用户输入、计算新的物理状态等。即在物理模拟步骤之后执行的操作。postStep事件是在每个物理时间步后被调用的事件。这个事件可以用于执行一些与物理更新后的状态更改相关的操作。所以我们可以监听在物体约束中被力冲击后断开约束。接下来将用代码演示。


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.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, 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 planeShape = new CANNON.Box(new CANNON.Vec3(10, 0.05, 10))const planeBody = new CANNON.Body({shape: planeShape,position: new CANNON.Vec3(0,0,0)})physicsWorld.addBody(planeBody)phyMeshes.push(planeBody)const planeGeometry = new THREE.BoxGeometry(20, 0.1, 20)const planeMaterial = new THREE.MeshBasicMaterial({wireframe: true})const planeMesh = new THREE.Mesh(planeGeometry,planeMaterial)scene.add(planeMesh)meshes.push(planeMesh)const sphereShape = new CANNON.Sphere(1)const sphereGeometry = new THREE.SphereGeometry(1, 16, 16)const sphereMaterial = new THREE.MeshBasicMaterial({color: 0xff0000, wireframe: true})let previousBodyfor(let i = 0; i < 10; i++) {const sphereBody = new CANNON.Body({shape: sphereShape,position: new CANNON.Vec3(0, 25 - i * 2.2 , 0),mass: i == 0 ? 0 : 1})physicsWorld.addBody(sphereBody)phyMeshes.push(sphereBody)const sphereMesh = new THREE.Mesh(sphereGeometry,sphereMaterial)scene.add(sphereMesh)meshes.push(sphereMesh)if (i > 0) {const constraint = new CANNON.DistanceConstraint(previousBody,sphereBody,2.2)physicsWorld.addConstraint(constraint)}previousBody = sphereBody}const sphereClickShape = new CANNON.Sphere(0.8)const sphereClickGeometry = new THREE.SphereGeometry(0.8, 16, 16)const sphereClickMaterial = new THREE.MeshBasicMaterial({color: 0x0000ff})window.addEventListener('click', () => {const sphereClickBody = new CANNON.Body({mass: 1,shape: sphereClickShape,position: new CANNON.Vec3(5, 15, 0)})physicsWorld.addBody(sphereClickBody)phyMeshes.push(sphereClickBody)sphereClickBody.velocity.set(-10, 0, 0)const sphereClickMesh = new THREE.Mesh(sphereClickGeometry, sphereClickMaterial)scene.add(sphereClickMesh)meshes.push(sphereClickMesh)})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>

2.2 效果

请添加图片描述
可以看到我们就有点击生成蓝色小球冲击的效果。


3、removeConstraint

cannon-es中,约束(Constraints)是用来限制或控制物体运动的一种机制。通过约束,可以将物体连接在一起,或者限制物体在某些方向上的运动。而removeConstraint方法,则是用来从物理世界中移除已经添加的约束的。

3.1 解除约束代码

    physicsWorld.addEventListener('postStep', () => {for(let i = 0; i < physicsWorld.constraints.length; i++) {const constraint = physicsWorld.constraints[i]// 获取约束力度的绝对值大小let multiplier = Math.abs(constraint.equations[0].multiplier)console.log(multiplier)if (multiplier > 1000) {// 约束破坏physicsWorld.removeConstraint(constraint)}}})

效果

请添加图片描述
可以看到我前面3次由于力度不够所以约束不能被破坏,第4下的力直接把约束破坏了。


4、完整代码

最后给出完整代码:

<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, 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 planeShape = new CANNON.Box(new CANNON.Vec3(10, 0.05, 10))const planeBody = new CANNON.Body({shape: planeShape,position: new CANNON.Vec3(0,0,0)})physicsWorld.addBody(planeBody)phyMeshes.push(planeBody)const planeGeometry = new THREE.BoxGeometry(20, 0.1, 20)const planeMaterial = new THREE.MeshBasicMaterial({wireframe: true})const planeMesh = new THREE.Mesh(planeGeometry,planeMaterial)scene.add(planeMesh)meshes.push(planeMesh)const sphereShape = new CANNON.Sphere(1)const sphereGeometry = new THREE.SphereGeometry(1, 16, 16)const sphereMaterial = new THREE.MeshBasicMaterial({color: 0xff0000, wireframe: true})let previousBodyfor(let i = 0; i < 10; i++) {const sphereBody = new CANNON.Body({shape: sphereShape,position: new CANNON.Vec3(0, 25 - i * 2.2 , 0),mass: i == 0 ? 0 : 1})physicsWorld.addBody(sphereBody)phyMeshes.push(sphereBody)const sphereMesh = new THREE.Mesh(sphereGeometry,sphereMaterial)scene.add(sphereMesh)meshes.push(sphereMesh)if (i > 0) {const constraint = new CANNON.DistanceConstraint(previousBody,sphereBody,2.2)physicsWorld.addConstraint(constraint)}previousBody = sphereBody}const sphereClickShape = new CANNON.Sphere(0.8)const sphereClickGeometry = new THREE.SphereGeometry(0.8, 16, 16)const sphereClickMaterial = new THREE.MeshBasicMaterial({color: 0x0000ff})let muscle = 0window.addEventListener('click', () => {const sphereClickBody = new CANNON.Body({mass: 1,shape: sphereClickShape,position: new CANNON.Vec3(5, 15, 0)})physicsWorld.addBody(sphereClickBody)phyMeshes.push(sphereClickBody)muscle++sphereClickBody.velocity.set(-10, 0, 0)if (muscle > 3) {sphereClickBody.velocity.set(-50, 0, 0)}const sphereClickMesh = new THREE.Mesh(sphereClickGeometry, sphereClickMaterial)scene.add(sphereClickMesh)meshes.push(sphereClickMesh)})physicsWorld.addEventListener('postStep', () => {for(let i = 0; i < physicsWorld.constraints.length; i++) {const constraint = physicsWorld.constraints[i]// 获取约束力度的绝对值大小let multiplier = Math.abs(constraint.equations[0].multiplier)console.log(multiplier)if (multiplier > 1000) {// 约束破坏physicsWorld.removeConstraint(constraint)}}})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>

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

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com