当前位置: 首页 > article >正文

学习threejs,使用Physijs物理引擎

👨‍⚕️ 主页: gis分享者
👨‍⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅!
👨‍⚕️ 收录于专栏:threejs gis工程师


文章目录

  • 一、🍀前言
    • 1.1 ☘️Physijs 物理引擎
      • 1.1.1 ☘️代码示例
      • 1.1.2 ☘️方法/属性
  • 二、🍀使用Physijs物理引擎
    • 1. ☘️实现思路
    • 2. ☘️代码样例


一、🍀前言

本文详细介绍如何基于threejs在三维场景中使用Physijs物理引擎,亲测可用。希望能帮助到您。一起学习,加油!加油!

1.1 ☘️Physijs 物理引擎

Three.js 的 Physi.js 是一个基于 Physijs 的物理引擎插件,用于为 Three.js 场景添加物理模拟(如碰撞检测、重力、刚体动力学等)。

1.1.1 ☘️代码示例

// 初始化 Physi.js 场景
const scene = new Physijs.Scene();// 创建带有物理效果的立方体
const box = new Physijs.BoxMesh(new THREE.BoxGeometry(1, 1, 1),new THREE.MeshBasicMaterial({ color: 0xff0000 })
);
scene.add(box);// 监听碰撞事件
box.addEventListener('collision', (otherObject) => {console.log('发生碰撞!', otherObject);
});// 在动画循环中更新物理
function animate() {requestAnimationFrame(animate);scene.simulate(); // 更新物理模拟renderer.render(scene, camera);
}
animate();

1.1.2 ☘️方法/属性

Physijs.Scene
创建支持物理的 Three.js 场景。

mesh.setLinearVelocity()
设置物体的线性速度(移动速度)。

mesh.setAngularVelocity()
设置物体的角速度(旋转速度)。

mesh.addEventListener()
监听碰撞事件(如 ‘collision’)。

new Physijs.BoxMesh()
创建带有长方体碰撞体的物体。

new Physijs.SphereMesh()
创建带有球体碰撞体的物体。

scene.simulate()
在渲染循环中调用,更新物理模拟。

Physijs.createMaterial(material, friction, restitution)
创建物理材质,影响摩擦力和弹性。
参数:
material:Three.js 材质(如 THREE.MeshPhongMaterial)。
friction:摩擦系数(默认 0.8)。
restitution:弹性系数(默认 0)。

二、🍀使用Physijs物理引擎

1. ☘️实现思路

  • 1、引入‘physi.js’,创建Physijs物理引擎三维场景scene,设置scene场景重力信息。
  • 2、初始化camera相机,定义相机位置 camera.position.set,设置相机方向camera.lookAt,场景scene添加camera。
  • 3、创建THREE.SpotLight聚光灯光源light,设置light位置,scene场景加入light。
  • 4、加载几何模型:使用‘floor-wood.jpg’木纹贴图创建地面网格对象ground以及四周突出边框网格对象borderLeft、borderRight、borderTop、borderBottom,ground添加borderLeft、borderRight、borderTop、borderBottom。定义controls方法,内部定义addCubes方法用于添加物理碰撞立方体,定义addSpheres方法用于添加物理碰撞球体,定义clearMeshes方法用于清除添加的碰撞对象,定义碰撞物体restitution弹性形变和friction摩擦系数。定义render方法,实现ground的旋转动画。具体代码参考下面代码样例。
  • 5、加入gui控制。加入stats监控器,监控帧数信息。

2. ☘️代码样例

<!DOCTYPE html>
<html>
<style>body {margin: 0;overflow: hidden;}
</style><head><title>学习threejs,使用Physijs物理引擎</title><script type="text/javascript" src="../libs/three.js"></script><script type="text/javascript" src="../libs/stats.js"></script><script type="text/javascript" src="../libs/physi.js"></script><script type="text/javascript" src="../libs/dat.gui.js"></script><script type="text/javascript" src="../libs/chroma.js"></script><script type="text/javascript">'use strict';//任务线程Physijs.scripts.worker = '../libs/physijs_worker.js';//内部库ammo.jsPhysijs.scripts.ammo = '../libs/ammo.js';var scale = chroma.scale(['white', 'blue', 'red', 'yellow']);var initScene, render, applyForce, setMousePosition, mouse_position,ground_material, box_material,projector, renderer, render_stats, physics_stats, scene, ground, light, camera, box, boxes = [];initScene = function () {renderer = new THREE.WebGLRenderer({antialias: true});renderer.setSize(window.innerWidth, window.innerHeight);renderer.setClearColor(new THREE.Color(0x000000));document.getElementById('viewport').appendChild(renderer.domElement);render_stats = new Stats();render_stats.domElement.style.position = 'absolute';render_stats.domElement.style.top = '1px';render_stats.domElement.style.zIndex = 100;document.getElementById('viewport').appendChild(render_stats.domElement);scene = new Physijs.Scene;scene.setGravity(new THREE.Vector3(0, -90, 0));camera = new THREE.PerspectiveCamera(35,window.innerWidth / window.innerHeight,1,1000);camera.position.set(80, 60, 80);camera.lookAt(scene.position);scene.add(camera);// Lightlight = new THREE.SpotLight(0xFFFFFF);light.position.set(20, 100, 50);scene.add(light);// Materialsground_material = Physijs.createMaterial(new THREE.MeshPhongMaterial({map: THREE.ImageUtils.loadTexture('../assets/textures/general/floor-wood.jpg')}),.9,.6);ground_material.map.wrapS = ground_material.map.wrapT = THREE.RepeatWrapping;ground_material.map.repeat.set(4, 8);// Groundground = new Physijs.BoxMesh(new THREE.BoxGeometry(60, 1, 130),ground_material,0);ground.receiveShadow = true;var borderLeft = new Physijs.BoxMesh(new THREE.BoxGeometry(2, 6, 130),ground_material,0);borderLeft.position.x = -31;borderLeft.position.y = 2;ground.add(borderLeft);var borderRight = new Physijs.BoxMesh(new THREE.BoxGeometry(2, 6, 130),ground_material,0);borderRight.position.x = 31;borderRight.position.y = 2;ground.add(borderRight);var borderBottom = new Physijs.BoxMesh(new THREE.BoxGeometry(64, 6, 2),ground_material,0);borderBottom.position.z = 65;borderBottom.position.y = 2;ground.add(borderBottom);var borderTop = new Physijs.BoxMesh(new THREE.BoxGeometry(64, 6, 2),ground_material,0);borderTop.position.z = -65;borderTop.position.y = 2;ground.add(borderTop)scene.add(ground);var meshes = [];var controls = new function () {//参数 restitution(弹性形变)和friction(摩擦系数)this.cubeRestitution = 0.4;this.cubeFriction = 0.4;this.sphereRestitution = 0.9;this.sphereFriction = 0.1;this.clearMeshes = function () {meshes.forEach(function (e) {scene.remove(e);});meshes = [];};this.addSpheres = function () {var colorSphere = scale(Math.random()).hex();for (var i = 0; i < 5; i++) {box = new Physijs.SphereMesh(new THREE.SphereGeometry(2, 20),Physijs.createMaterial(new THREE.MeshPhongMaterial({color: colorSphere,opacity: 0.8,transparent: truecontrols.sphereFriction,controls.sphereRestitution));box.position.set(Math.random() * 50 - 25,20 + Math.random() * 5,Math.random() * 50 - 25);meshes.push(box);scene.add(box);}};this.addCubes = function () {var colorBox = scale(Math.random()).hex();for (var i = 0; i < 5; i++) {box = new Physijs.BoxMesh(new THREE.BoxGeometry(4, 4, 4),Physijs.createMaterial(new THREE.MeshPhongMaterial({color: colorBox,opacity: 0.8,transparent: truecontrols.cubeFriction,controls.cubeRestitution));box.position.set(Math.random() * 50 - 25,20 + Math.random() * 5,Math.random() * 50 - 25);box.rotation.set(Math.random() * Math.PI * 2,Math.random() * Math.PI * 2,Math.random() * Math.PI * 2);meshes.push(box);scene.add(box);}}};var gui = new dat.GUI();gui.add(controls, 'cubeRestitution', 0, 1);gui.add(controls, 'cubeFriction', 0, 1);gui.add(controls, 'sphereRestitution', 0, 1);gui.add(controls, 'sphereFriction', 0, 1);gui.add(controls, 'addCubes');gui.add(controls, 'addSpheres');gui.add(controls, 'clearMeshes');requestAnimationFrame(render);scene.simulate();};var stepX;var direction = 1;render = function () {requestAnimationFrame(render);renderer.render(scene, camera);render_stats.update();ground.rotation.x += 0.002 * direction;if (ground.rotation.x < -0.4) direction = 1;if (ground.rotation.x > 0.4) direction = -1;ground.__dirtyRotation = true;scene.simulate(undefined, 1);};window.onload = initScene;</script>
</head><body>
<div id="viewport"></div>
</body></html>

效果如下:
在这里插入图片描述

相关文章:

学习threejs,使用Physijs物理引擎

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言1.1 ☘️Physijs 物理引擎1.1.1 ☘️…...

allure生成测试报告(搭配Pytest、allure-pytest)

文章目录 前言allure简介allure安装软件下载安装配置环境变量安装成功验证 allure运行流程allure装饰器函数基本说明装饰器函数使用allure.attach 命令行运行利用allure-pytest生成中间结果json 查看测试报告总览页面每个tab页的说明类别页面测试套图表页面时间刻度功能页面包 …...

龙虎榜——20250509

上证指数今天缩量&#xff0c;整体跌多涨少&#xff0c;走势处于日线短期的高位~ 深证指数今天缩量小级别震荡&#xff0c;大盘股表现更好~ 2025年5月9日龙虎榜行业方向分析 一、核心行业方向 军工航天 • 代表个股&#xff1a;航天南湖、天箭科技、襄阳轴承。 • 驱动逻辑…...

操作系统的初步了解

目录 引言&#xff1a;什么是操作系统&#xff1f; 一、设计操作系统的目的 二、操作系统是做什么的&#xff1a; 操作系统主要有四大核心任务&#xff1a; 1. 管理硬件 2. 运行软件 3. 存储数据 4. 提供用户界面 如何理解操作系统的管理呢&#xff1f; 1. 什么是操作…...

拆分sql数据,(shop_backup)sql文档过大(>5G)

执行表结构 sed -n /^-- Table structure/,/^-- Dumping data/p shop_backup.sql > structure.sql mysql -u root -p shop < structure.sql 执行数据 awk /^INSERT INTO/{if(count%1000001) {file"data_part_"i".sql"}; print > file} shop_bac…...

软件工程之软件项目管理深度解析

前文基础&#xff1a; 1.软件工程学概述&#xff1a;软件工程学概述-CSDN博客 2.软件过程深度解析&#xff1a;软件过程深度解析-CSDN博客 3.软件工程之需求分析涉及的图与工具&#xff1a;软件工程之需求分析涉及的图与工具-CSDN博客 4.软件工程之形式化说明技术深度解…...

基于Boost库、Jsoncpp、cppjieba、cpp-httplib等构建Boost搜索引擎

⭐️个人主页&#xff1a;小羊 ⭐️所属专栏&#xff1a;项目 很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~ 目录 项目背景技术栈和项目环境正排索引和倒排索引数据去标签与清洗下载数据源去标签 建立索引构建正排索引构建倒排索引 建立搜索引擎h…...

Qt 通过控件按钮实现hello world + 命名规范(7)

文章目录 使用编辑框来完成 hello world通过编辑图形化界面方式通过纯代码方式 通过按钮的方式来创建 hello world通过编辑图形化界面方式通过纯代码方式 总结Qt Creator中的快捷键如何使用文档命名规范 简介&#xff1a;这篇文章着重点并不在于创建hello world程序&#xff0c…...

JAVA继承中变量和方法的存储和方法中访问变量的顺序

一、变量归属与内存位置 static 变量&#xff1a;属于类&#xff0c;只存在一份&#xff0c;保存在方法区&#xff08;或元空间&#xff09;。 实例变量&#xff08;非static&#xff09;&#xff1a;属于对象&#xff0c;每个对象单独一份&#xff0c;保存在堆内存中。 二、…...

关于大数据的基础知识(二)——国内大数据产业链分布结构

成长路上不孤单&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a; 【14后&#x1f60a;///计算机爱好者&#x1f60a;///持续分享所学&#x1f60a;///如有需要欢迎收藏转发///&#x1f60a;】 今日分享关于大数据的基础知识&#xff08;二&a…...

【Python 字典(Dictionary)】

Python 中的字典&#xff08;Dictionary&#xff09;是最强大的键值对&#xff08;key-value&#xff09;数据结构&#xff0c;用于高效存储和访问数据。以下是字典的核心知识点&#xff1a; 一、基础特性 键值对存储&#xff1a;通过唯一键&#xff08;Key&#xff09;快速访…...

Linux 内核中的 security_sk_free:安全模块与 Socket 释放机制解析

引言 在 Linux 内核中,网络通信和进程间交互(IPC)的核心数据结构之一是 struct sock(即 socket)。其生命周期管理涉及复杂的资源分配与释放逻辑。本文聚焦于 security_sk_free 这一函数,探讨其作用、调用场景以及与安全模块的交互机制,并解答一个常见疑问:在单机间 TC…...

VBA -- 学习Day4

数组 创建数组&#xff1a; Dim 数组名&#xff08;数组元素上下角标&#xff09;[As 元素类型] eg. Dim MyArray (1 To 3) As Integer 注意&#xff1a;1.如果不指定元素类型&#xff0c;则是Variant类型 向数组赋值&#xff1a; eg. MyArray(1) 100 MyArray(2) 200…...

Winform(11.案例讲解1)

今天写两个案例,用于更好的理解控件的使用 在写之前先写一个类 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace _1.案例讲解 { internal class Student { public string …...

电机密集型工厂环境下的无线通信技术选型与优化策略

点击下面图片带您领略全新的嵌入式学习路线 &#x1f525;爆款热榜 88万阅读 1.6万收藏 在电机、变频器、电焊机等强电磁干扰源遍布的工业环境中&#xff0c;无线通信系统的可靠性面临严峻挑战。本文从抗干扰能力、传输稳定性、实时性需求三大核心维度出发&#xff0c;结合工…...

Web 自动化之 HTML JavaScript 详解

文章目录 一、HTML 常用标签二、javascript 脚本1、什么是 javascript(js)2、 js变量和函数3、js 弹窗处理4、js 流程控制语句和 switch 结构语句应用 一、HTML 常用标签 HTML&#xff1a;超文本标记语言 超文本&#xff1a;不仅只包含文字&#xff0c;还有超链接、视频…这些…...

一文了解氨基酸的分类、代谢和应用

氨基酸&#xff08;Amino acids&#xff09;是在分子中含有氨基和羧基的一类化合物。氨基酸是生命的基石&#xff0c;人类所有的疾病与健康状况都与氨基酸有直接或间接的关系。氨基酸失衡可引起肝硬化、神经系统感染性疾病、糖尿病、免疫性疾病、心血管疾病、肾病、肿瘤等各类疾…...

系统学习算法:动态规划(斐波那契+路径问题)

题目一&#xff1a; 思路&#xff1a; 作为动态规划的第一道题&#xff0c;这个题很有代表性且很简单&#xff0c;适合入门 先理解题意&#xff0c;很简单&#xff0c;就是斐波那契数列的加强版&#xff0c;从前两个数变为前三个数 算法原理&#xff1a; 这五步可以说是所有…...

jquery实现文字点选验证码

文字点选验证码是一种有效的防止自动化攻击的手段。用户需要按照提示顺序点击特定的文字&#xff0c;验证通过后才能进行下一步操作。本文将详细介绍如何使用jQuery实现这种验证码。 一、实现思路 生成验证码&#xff1a;随机生成一组文字&#xff0c;并随机排列在验证码区域…...

VTK|加载ply文件数据进行平移+高程渲染

文章目录 将 .ply 点云或模型数据进行 Elevation 着色并可视化渲染的完整流程&#x1f7e6; 1. **使用 ElevationFilter 给模型上色&#xff08;根据 Z 值&#xff09;**&#x1f7e9; 2. **构造 Jet 风格的 Lookup Table&#xff08;颜色映射表&#xff09;**&#x1f537; 3.…...

JAVA房屋租售管理系统房屋出租出售平台房屋销售房屋租赁房屋交易信息管理源码

一、源码描述 这是一套房屋租售管理源码&#xff0c;基于SpringBootVue框架&#xff0c;后端采用JAVA开发&#xff0c;源码功能完善&#xff0c;涵盖了房屋租赁、房屋销售、房屋交易等业务。 二、源码截图...

掌握Multi-Agent实践(三):ReAct Agent集成Bing和Google搜索功能,采用推理与执行交替策略,增强处理复杂任务能力

一个普遍的现象是,大模型通常会根据给定的提示直接生成回复。对于一些简单的任务,大模型或许能够较好地应对。然而,当我们面对更加复杂的任务时,往往希望大模型能够表现得更加“智能”,具备适应多样场景和解决复杂问题的能力。为此,AgentScope 提供了内置的 ReAct 智能体…...

AOP实现原理

AOP实现原理 背景实现常用注解 背景 感觉需要掌握, 对理解其他知识点有好处. 实现 动态代理实现. JDK 实现 InvacationHander CGLib Enhancer 轻量级的基于ASM字节码框架. 常用注解 Before After AfterRetruning AfterThrowing Around...

Bearer Token的神秘面纱:深入解析HTTP认证头的设计哲学

为何有些Token会带Bearer&#xff1f; 在接口测试与开发中&#xff0c;我们经常会遇到这样的请求头&#xff1a; Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... 这个神秘的"Bearer"前缀从何而来&#xff1f;为何不直接使用Authorization: Token..…...

【国产化】在银河麒麟ARM环境下离线安装docker

1、前言 采用离线安装的方式。 关于离线安装的方式官网有介绍&#xff0c;但是说的很简单&#xff0c;网址&#xff1a;Binaries | Docker Docs 官网介绍的有几种主流linux系统的安装方式&#xff0c;但是没有kylin的&#xff0c;所以在此记录一下。 在安装过程中也遇到了些…...

K8S - Harbor 镜像仓库部署与 GitLab CI 集成实战

引言 在 Kubernetes 环境中&#xff0c;容器镜像的存储与管理至关重要。企业级镜像仓库&#xff08;如 Harbor&#xff09;为团队提供了安全、稳定、可扩展的镜像管理解决方案。 一、Harbor 安装与配置 Harbor 是由 VMware 开源的企业级云原生镜像仓库&#xff0c;它不仅支持…...

ASCII码的快速记忆方法

当然&#xff01;记住ASCII码的关键是找到规律和分组记忆。以下是一些快速记忆的方法&#xff1a; 1. 记住关键分界点 0~31&#xff1a;控制字符&#xff08;不可打印&#xff0c;如换行、制表符等&#xff09;&#xff0c;不需要全记&#xff0c;知道0是NULL&#xff0c;10是…...

java volatile关键字

volatile 是 Java 中用于保证多线程环境下变量可见性和禁止指令重排序的关键字。 普通变量不加volatile修饰有可见性问题&#xff0c;即有线程修改该变量值&#xff0c;其他线程无法立即感知该变量值修改了。代码&#xff1a; private static int intVal 0; // 普通变量未加 …...

解决SQL Server SQL语句性能问题(9)——正确使用索引

前述章节中,我们介绍和讲解了SQL调优所需要的基本知识和分析方法,那么,通过前述这些知识和方法定位到问题后,接下来,我们该怎么做呢?那就是本章的内容,给出解决SQL语句性能问题的、科学而合理的方案和方法。 本章主要对解决SQL语句性能问题的几种常用方法进行说明和讲解…...

Vibe Coding: 优点与缺点

如果你最近在开发圈子里,你很可能听说过这个新趋势"vibe coding"(氛围编程)。 我只能说我对此感受复杂。以下是原因。 优势 在构建新项目时,靠着氛围编程达到成功感觉很自由!但对于遗留代码来说情况就不同了,尽管也不是不可能。 实时反馈和快速迭代 Cursor(…...