Threejs之球发射实战
本文目录
- 前言
- 一、效果预览
- 二、代码实现及解析
- 2.1 代码
- 2.2 解析
前言
本篇将基于Threejs之模拟小球反弹基础上以及Threejs这个专栏学习过的知识点上进行小球更加真实的物理运动轨迹,并且还会与鼠标进行交互的操作。由于知识点都在上篇均有涉及,本篇就不过多赘述了。
一、效果预览
最终效果预览:

可以看到,我们完成鼠标点击生成小球,并且小球带有阴影以及贴合现实世界的物理行为,下落,旋转,碰撞。
二、代码实现及解析
2.1 代码
废话不多说直接上代码:
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>html,body {margin: 0;padding: 0;width: 100%;height: 100%;}</style>
</head><body><script type="module">// 倒入轨道控制器import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';import * as THREE from "three";import * as CANNON from "cannon";// 创建场景const scene = new THREE.Scene();scene.background = new THREE.Color(0xffffff);// 创建相机const camera = new THREE.PerspectiveCamera( // 透视相机45, // 视角 角度数window.innerWidth / window.innerHeight, // 宽高比 占据屏幕0.1, // 近平面(相机最近能看到物体)1000, // 远平面(相机最远能看到物体));camera.position.set(0, 2, 20);// 创建渲染器const renderer = new THREE.WebGLRenderer({antialias: true, // 抗锯齿});// 设置渲染器宽高renderer.setSize(window.innerWidth, window.innerHeight);// renderer(渲染器)的dom元素添加到我们的HTML文档中document.body.appendChild(renderer.domElement);// 加入灯光const light = new THREE.PointLight( 0xffffff, 1000, 100 );light.position.set(0,20,0);const pointLightHelper = new THREE.PointLightHelper( light, 1 );scene.add( pointLightHelper );scene.add( light );const ambientLight = new THREE.AmbientLight( 0x404040, 100 ); // 柔和的白光scene.add( ambientLight );// 地面const plane = new THREE.Mesh(new THREE.PlaneGeometry(40, 40),new THREE.MeshStandardMaterial({color: 0x817936}));plane.rotation.x = -Math.PI/2;// 添加到场景中scene.add(plane);renderer.shadowMap.enabled = true;plane.receiveShadow = true;light.castShadow = true;// 创建物理世界const physicsWorld = new CANNON.World();// 设置y轴重力physicsWorld.gravity.set(0, -9.82, 0);// 创建物理材料const groundMaterial = new CANNON.Material('groundMaterial');const sphereMaterial = new CANNON.Material('sphereMaterial');const contactMaterial = new CANNON.ContactMaterial(groundMaterial, sphereMaterial, {restitution: 0.7 // 弹性});physicsWorld.addContactMaterial(contactMaterial);// 创建物理地面const groundBody = new CANNON.Body({mass: 0, // 为0表示地面不受重力影响shape: new CANNON.Plane(), // 物体的形状,cannon中地面形状物体material: groundMaterial,});groundBody.quaternion.setFromEuler(-Math.PI / 2, 0, 0); // 将地面绕着x轴旋转90度成为真正的地面physicsWorld.addBody(groundBody);// 加载贴图const loader = new THREE.TextureLoader();const texture = loader.load("../images/rabbit.png")// 多个小球,创建小球数组let spheresArr = [];// 动态生成小球const createSphere = (position, direction) => { // 接收两个参数 position:小球生成的位置,direction小球超哪发射位置const radius = 1;// 创建可视化小球const geometry = new THREE.Mesh(new THREE.SphereGeometry(radius, 32, 32), new THREE.MeshPhongMaterial({map: texture}));geometry.castShadow = true;geometry.position.copy(position);scene.add(geometry);// 创建物理小球刚体const sphereBody = new CANNON.Body({mass: 0.5, // 质量设为1material: sphereMaterial,linearDamping: 0.5, // 模拟空气阻力});// 创建物理小球const sphereShape = new CANNON.Sphere(radius);sphereBody.position.copy(position);sphereBody.addShape(sphereShape); // 刚体添加形状也可这种写法sphereBody.applyLocalForce(direction.scale(600), // 施加的力的向量new CANNON.Vec3(0, 0, 0) // 力作用的点在刚体的局部坐标系中的位置); // 在刚体的局部坐标系中的指定点上施加一个力physicsWorld.addBody(sphereBody);spheresArr.push({geometry,sphereBody})}renderer.domElement.addEventListener('mouseup', (event) => {// console.log(spheresArr);const mouse = new THREE.Vector2();mouse.x = (event.clientX / window.innerWidth) * 2 - 1;mouse.y = -(event.clientY / window.innerWidth) *2 + 1;const raycaster = new THREE.Raycaster();raycaster.setFromCamera(mouse,camera);const pos = new THREE.Vector3();pos.copy(raycaster.ray.direction); // 鼠标点击的射线方向pos.add(raycaster.ray.origin); // 射线原点const direction = new CANNON.Vec3(raycaster.ray.direction.x,raycaster.ray.direction.y,raycaster.ray.direction.z,)createSphere({x:pos.x, y:pos.y, z:pos.z}, direction);})const updatePhysic = () => { // 因为这是实时更新的,所以需要放到渲染循环动画animate函数中physicsWorld.step(1/60);spheresArr.forEach(({geometry,sphereBody}) => {geometry.position.copy(sphereBody.position); // 将物理刚体小球的位置赋值给threejs的小球geometry.quaternion.copy(sphereBody.quaternion); // 将物理刚体小球的旋转赋值给threejs的小球})}// 控制器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>
</body>
</html>
2.2 解析
重点代码解析:
- 小球阴影:重点添加灯光,以及受灯光影响的材质。
const light = new THREE.PointLight( 0xffffff, 1000, 100 );添加点光源。地面为受灯光影响的new THREE.MeshStandardMaterial({color: 0x817936})材质以及小球受灯光影响材质ew THREE.MeshPhongMaterial({map: texture})。并且打开阴影开光:renderer.shadowMap.enabled = true; plane.receiveShadow = true; light.castShadow = true; geometry.castShadow = true;- 动态交互事件
renderer.domElement.addEventListener('mouseup', callback)这是鼠标交互的关键。- 每次点击都动态生成可视小球及刚体小球,并且都放到数组里:
spheresArr.push({geometry,sphereBody})- 获取鼠标点击时的二维向量
const mouse = new THREE.Vector2();mouse.x = (event.clientX / window.innerWidth) * 2 - 1;mouse.y = -(event.clientY / window.innerWidth) *2 + 1;- 射线方向及射线原点
const raycaster = new THREE.Raycaster();raycaster.setFromCamera(mouse,camera);const pos = new THREE.Vector3();pos.copy(raycaster.ray.direction); // 鼠标点击的射线方向pos.add(raycaster.ray.origin); // 射线原点const direction = new CANNON.Vec3(raycaster.ray.direction.x,raycaster.ray.direction.y,raycaster.ray.direction.z,)
在学习的路上,如果你觉得本文对你有所帮助的话,那就请关注点赞评论三连吧,谢谢,你的肯定是我写博的另一个支持。
相关文章:
Threejs之球发射实战
本文目录 前言一、效果预览二、代码实现及解析2.1 代码2.2 解析 前言 本篇将基于Threejs之模拟小球反弹基础上以及Threejs这个专栏学习过的知识点上进行小球更加真实的物理运动轨迹,并且还会与鼠标进行交互的操作。由于知识点都在上篇均有涉及,本篇就不过…...
详解新规|逐条分析《电子认证服务管理办法(征求意见稿)》修订重点
近日,工信部就《电子认证服务管理办法(征求意见稿)》公开征求意见。 来源|公开资料 图源|Pixabay 编辑|公钥密码开放社区 《电子认证服务管理办法》(以下简称《办法》)于2009年2…...
哪个编程工具让你的工作效率翻倍?
✍️作者简介:小北编程(专注于HarmonyOS、Android、Java、Web、TCP/IP等技术方向) 🐳博客主页: 开源中国、稀土掘金、51cto博客、博客园、知乎、简书、慕课网、CSDN 🔔如果文章对您有一定的帮助请…...
SEW变频器的特点
SEW变频器是德国SEW-EURODRIVE GmbH公司生产的一种变频器产品,该公司是全球领先的驱动技术和系统解决方案提供商之一。以下是关于SEW变频器的详细介绍: 一、产品特点 高效节能:SEW变频器采用先进的电力电子技术和控制技术,能够实…...
大象机械人------1、关节控制
回到首页 目录 1 单关节控制 角度控制:1.1 send_angle(id, degree, speed)电位值控制:1.2 set_encoder(joint_id, encoder) 2 多关节控制 获取所有角度:2.1 get_angles()角度控制:2.2 send_angles(degrees, speed)电位值控制&…...
油电叉车倒车防撞报警系统精准探测
油电叉车倒车防撞报警系统通过集成最新的传感器技术、图像识别算法以及智能控制技术,通过实时监测叉车周围环境中的障碍物、行人和其他叉车,及时发出警报,避免可能的碰撞事故。 油电叉车倒车防撞报警系统功能详解 精准探测 叉车倒车时&a…...
Java学习路线:从零基础到高级开发者的完整指南
初学者入门指南 1. 环境搭建 安装JDK: 下载并安装最新版本的JDK(Java Development Kit)。配置环境: 设置JAVA_HOME环境变量,并将bin目录添加到PATH中。选择IDE: 使用Eclipse、IntelliJ IDEA或其他任何你喜欢的Java集成开发环境。 2. Java基…...
【Java算法】递归
🔥个人主页: 中草药 🔥专栏:【算法工作坊】算法实战揭秘 🍇一.递归 概念 递归是一种解决问题的方法,其中函数通过调用自身来求解问题。这种方法的关键在于识别问题是否可以被分解为若干个相似但规模更小…...
NIDS——suricata(三)
一、监控ICMP流量 1、ICMP流量特征 四大特征分别为:消息类型(Type)、代码(Code)、校验和(Checksum)、数据字段(Data Field)。这里我们使用 type消息类型。 ICMP 消息的类…...
运动耳机哪个牌子最好用?年度精选五款好用的骨传导耳机推荐
相信大家都已经深有体会,拿那种常规的入耳式无线蓝牙耳机来做运动耳机,很难满足运动需要。如果选择前两年流行的颈挂式无线运动蓝牙耳机,虽然简单轻巧,但也是入耳式设计,长时间佩戴耳朵不舒服。这样看来,运…...
鞋服企业信息化建设若干架构分享
鞋服企业的信息化建设有着自身的一些特点,这些特点主要体现在以下几个方面: 集成化:鞋服企业的信息化建设往往需要集成多种系统,如企业资源规划系统(ERP)、客户关系管理系统(CRM)、供…...
比较顺序3s1和3s2的搜索难度
在行列可自由变换的平面上,3点结构只有6个 (A,B)---6*30*2---(0,1)(1,0) 分类A和B,让A是6个3点结构,让B全是0。当收敛误差为7e-4,收敛199次取迭代次数平均值, 让训练集A-B矩阵的高分别是3,4,5…...
Vue3 el-switch @change事件在初始化时会自动调用问题
接收一个vue3项目,突然有一天,table里有个switch开关,请求数据之后就开始执行switch的change事件,我还啥都没操作,就报一推重复请求 <template><el-switch v-model"rec" inline-prompt :active-val…...
全面解析性能测试中的瓶颈分析与优化策略!
在软件开发的生命周期中,性能测试是确保应用程序在不同负载下稳定运行的关键步骤。性能瓶颈是导致系统性能下降的主要原因,及时发现并解决这些瓶颈,能够显著提升系统的响应速度和用户体验。本文将深入探讨性能测试中的瓶颈分析方法与优化策略…...
2018年Android面试题含答案--适合中高级(下)
熟悉Android系统的童鞋都知道,系统出于体验和性能上的考虑,app在退到后台时系统并不会真正的kill掉这个进程,而是将其缓存起来。打开的应用越多,后台缓存的进程也越多。在系统内存不足的情况下,系统开始依据自身的一套…...
基于SSM的汽车租赁系统+LW示例参考
系列文章目录 1.基于SSM的洗衣房管理系统原生微信小程序LW参考示例 2.基于SpringBoot的宠物摄影网站管理系统LW参考示例 3.基于SpringBootVue的企业人事管理系统LW参考示例 4.基于SSM的高校实验室管理系统LW参考示例 5.基于SpringBoot的二手数码回收系统原生微信小程序LW参考示…...
[晕事]今天做了件晕事44 wireshark 首选项IPv4:Reassemble Fragented IPv4 datagrams
不知不觉,已经来到了晕事系列的第四十四个晕事。今天办的晕事和Wireshark查看网络包相关。说,在Wireshark的编辑-首选项协议里的IPv4协议,有一个参数设置是:Reassemble Fragented IPv4 datagrams。 这个参数的含义是指定Wireshar…...
Unity人工智能开发学习心得
在Unity中进行人工智能研究与应用主要集中在几个关键领域,包括使用Unity ML-Agents插件进行强化学习、利用神经网络技术和深度学习技术训练AI,以及基于行为树技术设计游戏人工智能。 使用Unity ML-Agents插件进行强化学习:Unity ML-Agent…...
0911,类与类之间的关系,设计原则,工厂模式
01_figure.cc //简单工厂 #include <math.h> #include <iostream> #include <string> #include <memory>using std::cout; using std::endl; using std::string; using std::unique_ptr;//-------------------------------------------------// /…...
【2024最新版】零基础Python快速入门篇
完整代码已打包,需要的小伙伴可以戳这里 [学习资料] 安装和运行 1.安装 要使用"Python"首先要把它安装到你电脑里。打开 [Python官网]下载安装包。 在Windows上安装 打开安装包,选择"Use admin privileges when installing py.exe&qu…...
Linux应用开发之网络套接字编程(实例篇)
服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...
MPNet:旋转机械轻量化故障诊断模型详解python代码复现
目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...
Spring Boot 实现流式响应(兼容 2.7.x)
在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...
AI Agent与Agentic AI:原理、应用、挑战与未来展望
文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例:使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例:使用OpenAI GPT-3进…...
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...
React Native在HarmonyOS 5.0阅读类应用开发中的实践
一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强,React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 (1)使用React Native…...
CocosCreator 之 JavaScript/TypeScript和Java的相互交互
引擎版本: 3.8.1 语言: JavaScript/TypeScript、C、Java 环境:Window 参考:Java原生反射机制 您好,我是鹤九日! 回顾 在上篇文章中:CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...
高危文件识别的常用算法:原理、应用与企业场景
高危文件识别的常用算法:原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件,如包含恶意代码、敏感数据或欺诈内容的文档,在企业协同办公环境中(如Teams、Google Workspace)尤为重要。结合大模型技术&…...
重启Eureka集群中的节点,对已经注册的服务有什么影响
先看答案,如果正确地操作,重启Eureka集群中的节点,对已经注册的服务影响非常小,甚至可以做到无感知。 但如果操作不当,可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...
Windows安装Miniconda
一、下载 https://www.anaconda.com/download/success 二、安装 三、配置镜像源 Anaconda/Miniconda pip 配置清华镜像源_anaconda配置清华源-CSDN博客 四、常用操作命令 Anaconda/Miniconda 基本操作命令_miniconda创建环境命令-CSDN博客...
