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

Vue3 + Three.js + gltf-pipeline大型园区场景渲染与3D业务

在非使用unity作为3D渲染方案的前提下,对与目前web开发者比较友好的除了canvas场景需要的2D babylon.jsfabric.js, Three.js是目前针对于jsWeb用户最直接且比较友好的3D引擎方案了。
准备工作:
1.明确需要用的场景方案都有那些,模型需要的加载器是什么
2.模型的场景大小已经相关的交互业务
3.场景的工作环境(浏览器及硬件要求)
step1:
以.glb模型为例

import * as THREE from "three";
import {GLTFLoader} from "three/examples/jsm/loaders/GLTFLoader";
import {OrbitControls} from "three/examples/jsm/controls/OrbitControls";

以上就是一个场景绘制需要的基本3个要素
模型压缩
由于建模工程师因为场景规模的原因模型在建立时过多了使用了面,导致整个模型的体积很大,一个校区或者大园区为例,建筑加环境要素及周边地形都整体的模型体积已经达到了100M+,这个时候就需要我们在开发前就考虑模型的压缩问题了
DRACO压缩算法

npm install -g gltf-pipeline
--input, -i                   Path to the glTF or glb file.[string] [required]
--output, -o                  Output path of the glTF or glb file. Separate   resources will be saved to the same directory.  [string]
--binary, -b                  Convert the input glTF to glb.                                      //将输入的glTF转换为glb[boolean] [default: false]
--json, -j                    Convert the input glb to glTF.                                      //将输入的glb转换为glTF[boolean] [default: false]
--separate, -s                Write separate buffers, shaders, and textures                       //编写单独的缓冲区、着色器和纹理而不是把它们嵌入到glTF中instead of embedding them in the glTF.          [boolean] [default: false]
--separateTextures, -t        Write out separate textures only.                                   //只写出单独的纹理[boolean] [default: false]
--stats                       Print statistics to console for output glTF                         //将统计信息打印到控制台以输出glTF文件file.                 [boolean] [default: false]     
--keepUnusedElements          Keep unused materials, nodes and meshes.                            //保留未使用的材质、节点和网格[boolean] [default: false]
--draco.compressMeshes, -d    Compress the meshes using Draco. Adds the                            //使用Draco压缩网格。添加KHR_draco_mesh_压缩扩展KHR_draco_mesh_compression extension.[boolean] [default: false]
--draco.compressionLevel      Draco compression level [0-10], most is 10,                           //Draco压缩级别[0-10],大多数是10,最小值为0。值为0将会连续应用 编码并保留face顺序。least is 0. A value of 0 will apply sequentialencoding and preserve face order.[number] [default: 7]   
--draco.quantizePositionBits  Quantization bits for position attribute when                        //位置坐标属性的量化位使用Draco压缩。using Draco compression.  [number] [default: 11]--draco.quantizeNormalBits    Quantization bits for normal attribute when                           //法线属性的量化位使用Draco压缩using Draco compression.   [number] [default: 8]--draco.quantizeTexcoordBits  Quantization bits for texture coordinate                               //纹理坐标的量化位属性。attribute when using Draco compression.[number] [default: 10]--draco.quantizeColorBits     Quantization bits for color attribute when using                        //使用时颜色属性的量化位德拉科压缩Draco compression.         [number] [default: 8]--draco.quantizeGenericBits   Quantization bits for skinning attribute (joint                        //蒙皮属性(关节的量化位索引和关节权重)ad自定义属性使用Draco压缩时。indices and joint weights) ad custom attributeswhen using Draco compression. [number] [default: 8]--draco.uncompressedFallback  Adds uncompressed fallback versions of the                            //添加未压缩的回退版本压缩网格compressed meshes.    [boolean] [default: false]--draco.unifiedQuantization   Quantize positions of all primitives using the            //统一定义的量化网格所有基本体的边界框。 如果这个选项未设置,对每个应用量化原始的可能会导致差距出现在不同图元之间。same quantization grid defined by the unifiedbounding box of all primitives. If this optionis not set, quantization is applied on eachprimitive separately which can result in gapsappearing between different primitives.[boolean] [default: false]

在这里插入图片描述
gltf-pipeline的参数有很多这里我们只需要提炼出一个满足我们需要的就够了

gltf-pipeline -i .\public\tep\23.glb -o .\public\tep\23-main.glb  -d --draco.compressionLevel 9 --draco.quantizePositionBits 10 --draco.quantizeColorBits 10
-i .\public\cascl\caa4.glb   //输入路径-o .\public\cascl\caa4-main.glb  //输出路径及名称-d --draco.compressionLevel 10 //压缩等级--draco.quantizePositionBits 20  //量化  0 标识无损压缩 

需要注意的是安装好之后是不可以直接运行的我们需要一个three.js为我们提供的基本依赖draco_decoder.js 这个文件一般就放在node_module/three/examples/js/libs/draco目录下cpoy出来与模型文件一起放在public文件夹下即可

完成上述这些准备工作之后我们开始渲染我们的第一个大园区场景,因为我们使用了压缩算法所以我们需要额外再引入一个解压加载器,并将我们copy出来的draco_decoder.js文件与我们压缩好的模型都放在public下

import {DRACOLoader} from "three/examples/jsm/loaders/DRACOLoader"

step2
初始一个加载模型的方法

export const initMod=(id,filePath,fun)=>{container=document.getElementById(id);scene = new THREE.Scene();camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);renderer = new THREE.WebGLRenderer({ antialias: true,alpha: true });renderer.setSize(container.clientWidth, container.clientHeight);container.appendChild(renderer.domElement);renderer.setClearColor('#6fc0ec', 1.0);renderer.outputEncoding = THREE.sRGBEncoding;const loader = new GLTFLoader();let dracoLoader = new DRACOLoader();dracoLoader.setDecoderPath("/cascl/"); // 设置public下的解码路径,注意最后面的/dracoLoader.setDecoderConfig({ type: "js" });dracoLoader.preload();loader.setDRACOLoader(dracoLoader);loader.load(filePath,gltf => {// 将模型放到中间const box = new THREE.Box3().setFromObject(gltf.scene);const size = box.getSize(new THREE.Vector3()).length();const center = box.getCenter(new THREE.Vector3());gltf.scene.position.x -= center.x;gltf.scene.position.y -= center.y;gltf.scene.position.z -= center.z;camera.near = size / 100;camera.far = size * 100;camera.updateProjectionMatrix();camera.position.copy(center);camera.position.x += size / 2;camera.position.y += size / 2;camera.position.z += size / 2;camera.lookAt(center);scene.add(gltf.scene);console.log('---加载的模型',gltf.scene)const ambient = new THREE.AmbientLight(0xffffff, 0.4);scene.add(ambient);//添加在模型的右上角高三倍设置一个光源 太阳const light = new THREE.DirectionalLight(0xffffff, 1);// 模型宽度const width = box.max.x - box.min.x;// 模型高度const height = box.max.y - box.min.y;// 模型深度const depth = box.max.z - box.min.z;light.position.set(width * 3, height * 3, depth * 3);scene.add(light);
// 点光源let point = new THREE.PointLight('#74beee',1);point.position.set(-width * 3, -height * 3, depth * 3); // 点光源位置scene.add(point); // 点光源添加到场景中//多设置几个光源const light3 = new THREE.DirectionalLight('#8dccee', 1);light3.position.set(-width * 3, -height * 3, depth * 3);scene.add(light3);const light4 = new THREE.HemisphereLight('#8dccee', 0.3);scene.add(light4);//包含关键帧动画的模型作为参数创建一个播放器mixer = new THREE.AnimationMixer(gltf.scene);//  获取gltf.animations[0]的第一个clip动画对象clipAction = mixer.clipAction(gltf.animations[0]); //创建动画clipAction对象clipAction.play(); //播放动画
//不循环播放clipAction.loop = THREE.LoopOnce;
// 物体状态停留在动画结束的时候clipAction.clampWhenFinished = true// 如果想播放动画,需要周期性执行`mixer.update()`更新AnimationMixer时间数据clock = new THREE.Clock();},undefined,error => {console.error(error);});camera.position.z = 5;// 添加OrbitControls控制器controls = new OrbitControls(camera, renderer.domElement);controls.enableDamping = true;controls.dampingFactor = 0.05;controls.screenSpacePanning = false;controls.minDistance = 1;controls.maxDistance = 1000;const tag = labelTag({x: -580,y:50,z: -705});tagList.push(tag)scene.add(tag);//添加到指定的场景里renderLabel()animate();runLoop()renderer.domElement.addEventListener('click', handleModClick, false)
}

上方的初始方案中包含了一个基本的动画加载器由此我们可以完成一个基本的模型加载的场景创建
在这里插入图片描述
这是一个可以执行楼层分层爆炸的模型内置的动画由:

   //包含关键帧动画的模型作为参数创建一个播放器mixer = new THREE.AnimationMixer(gltf.scene);

完成捕捉及后续播放
step3
接下来我们完成园区的业务需求建设
1.场景需要有天空背景
2.场景需要有关键建筑的标注
3.场景的交互具有高亮环绕
4.场景具有漫游功能
基于以上我们开始增加需要的工具

  1. 场景漫游动画处理库
import TWEEN from '@tweenjs/tween.js';

2.场景天空环境即天空盒

    const urls = ['../sky/Above Day B_Cam_3_Right-X.png',//x正方形'../sky/Above Day B_Cam_2_Left+X.png',//x负方向'../sky/Above Day B_Cam_4_Up+Y.png',//y正方形'../sky/Above Day B_Cam_5_Down-Y.png',//y负方向'../sky/Above Day B_Cam_0_Front+Z.png',//z正方形'../sky/Above Day B_Cam_1_Back-Z.png'//z负方形]const textureCube = new THREE.CubeTextureLoader().load(urls)scene.background = textureCube

3.场景后处理器

import {EffectComposer} from 'three/examples/jsm/postprocessing/EffectComposer';
import {RenderPass} from 'three/examples/jsm/postprocessing/RenderPass';
import {OutlinePass} from 'three/examples/jsm/postprocessing/OutlinePass';

在使用了后处理器后因为模型抗拒齿原因我们需要在额外补充一个

import {SMAAPass} from 'three/examples/jsm/postprocessing/SMAAPass';//抗锯齿后处理const smaaPass = new SMAAPass(container.clientWidth * pixelRatio, container.clientHeight * pixelRatio);

4.一个漫游动画控制的方法

export const createCameraTween = (pos2, pos) => {tween = new TWEEN.Tween({// 相机开始坐标x: camera.position.x,y: camera.position.y,z: camera.position.z,// 相机开始指向的目标观察点tx:  current.x,ty:   current.y,tz:   current.z,}).to({// 相机结束坐标x: pos.x,y: pos.y,z: pos.z,// 相机结束指向的目标观察点tx: pos.x,ty: pos.y,tz: pos.z,}, 2000).onUpdate(function (obj) {// 动态改变相机位置camera.position.set(obj.x, obj.y, obj.z);// 动态计算相机视线camera.lookAt(pos.x, pos.y, -pos.z);}).start();animates();
}
const animates = (time) => {TWEEN.update(time);requestAnimationFrame(animates);
}

在使用glb/gltf模型中我们也常常会需要处理模型加载发暗,材质渲染失真的情况这里我们也一并加入到初始化的方案内

import {GammaCorrectionShader} from'three/examples/jsm/shaders/GammaCorrectionShader';
import {ShaderPass} from 'three/examples/jsm/postprocessing/ShaderPass';
import {RoomEnvironment} from 'three/examples/jsm/environments/RoomEnvironment';

由此我们以及基本完成了所有的加载需要的必备条件即要求,我们渲染一个大园区场景
在这里插入图片描述
在这里插入图片描述
场景后处理的效果业务由:

const renderOutline = (mod) => {if (buildIds.includes(mod.name)) {// 创建后处理对象EffectComposer,WebGL渲染器作为参数composer = new EffectComposer(renderer);renderPass = new RenderPass(scene, camera);composer.addPass(renderPass);
// 创建OutlinePass通道container = document.getElementById('mod') ? document.getElementById('mod') : document.getElementById('mod2');const v2 = new THREE.Vector2(container.clientWidth, container.clientHeight);const outlinePass = new OutlinePass(v2, scene, camera);// 创建伽马校正通道const gammaPass = new ShaderPass(GammaCorrectionShader);composer.addPass(gammaPass);const pixelRatio = renderer.getPixelRatio()//抗锯齿后处理const smaaPass = new SMAAPass(container.clientWidth * pixelRatio, container.clientHeight * pixelRatio);composer.addPass(smaaPass);outlinePass.selectedObjects = [mod];outlinePass.visibleEdgeColor.set('#a838ef');outlinePass.edgeThickness = 4;outlinePass.edgeStrength = 15;outlinePass.pulsePeriod = 3;composer.addPass(outlinePass);animateOutline()bus.$emit('showMod', mod)} else {clearOutline();}
}

由于业务延展很多不再过的的赘述,解决方案包含了动态标签切换,标记交互,灯光动态,场景灯光随相机,标签随相机,场景模型过滤,场景模型设备等状态动态更新,单楼层模型,室内模型控制切换即各类物联网设备交互等等。

相关文章:

Vue3 + Three.js + gltf-pipeline大型园区场景渲染与3D业务

在非使用unity作为3D渲染方案的前提下,对与目前web开发者比较友好的除了canvas场景需要的2D babylon.js,fabric.js, Three.js是目前针对于jsWeb用户最直接且比较友好的3D引擎方案了。 准备工作: 1.明确需要用的场景方案都有那些,模…...

基于FPGA的PS端的Si5340的控制

1、功能 Si5340/41-D可以输出任意频率,当然有范围,100Hz1GHz。外部输入为24M或者4854M的XTAL,VCO在13500~14256Mhz之间,控制接口采用IIC或者SPI。 芯片架构图 2、IIC控制方式 3、直接上控制代码 使用米联客ZU3EG,将…...

安装 Lua 的 HTTP 库

首先,你需要安装 Lua 的 HTTP 库。可以使用 LuaRocks 来安装。以下是安装命令: luarocks install http然后,你可以使用以下代码来爬取网页内容: local http require http-- 设置代理信息 http.set_proxy(jshk.com.cn)-- 网页UR…...

Redis解决缓存问题

目录 一、引言二、缓存三、Redis缓存四、缓存一致性1.缓存更新策略2.主动更新 五、缓存穿透六、缓存雪崩七、缓存击穿1.基于互斥锁解决具体业务2.基于逻辑过期解决具体业务 一、引言 在一些大型的网站中会有十分庞大的用户访问流量,而过多的用户访问对我们的MySQL数…...

七个合法学习黑客技术的网站,让你从萌新成为大佬

大家好我是若风,一个8年网络安全攻防经验的白帽黑客。 合法的学习网站,以下这些网站,虽说不上全方位的满足你的需求,但是大部分也都能。能带你了解到黑客有关的技术,视频,电子书,实践&#xff0…...

【数据结构】面试OJ题——带环链表(数学推论)

目录 1.环形链表Ⅰ ​编辑 思路 : 思路拓展 问题一: 问题二: 总结: 问题三: 证明总结第三点 总结: 2. 环形链表Ⅱ 思路一 思路二 3.相交链表 思路: 1.环形链表Ⅰ 141. 环形链…...

PostgreSQL中pg_ctl工具的使用

pg_ctl工具有以下功能: (1)初始化postgresql数据库实例 (2)启动、终止或重启postgresql数据库服务 (3)查看postgresql数据库服务的状态 (4)让数据库实例重新读取配置…...

深入理解Kafka3.6.0的核心概念,搭建与使用

Kafka是最初由Linkedin公司开发,是一个分布式、支持分区的(partition)、多副本的(replica),基于zookeeper协调的分布式消息系统,它的最大的特性就是可以实时的处理大量数据以满足各种需求场景&a…...

【python】编程题小代码

空心题(平行四边形) layer int(input("请输入你要打印的行数:")) for i in range(1,layer // 2 2): space_num layer - i for j in range(0,space_num): print(" ",end "") star_num 2 * i - 1 for j in range(0,sta…...

抖音小程序开发全攻略:如何规划项目和选择合适的开发团队

在数字化时代,抖音小程序成为企业推广和服务的重要渠道。本文将为您提供抖音小程序开发的全面攻略,重点介绍如何规划项目和选择合适的开发团队,并附有一些关键的技术代码示例。 1. 项目规划 在开始抖音小程序开发之前,详细的项…...

PSP - 蛋白质复合物结构预测 模版配对(Template Pair) 逻辑的特征分析

欢迎关注我的CSDN:https://spike.blog.csdn.net/ 本文地址:https://spike.blog.csdn.net/article/details/134328447 在 蛋白质复合物结构预测 的过程中,模版 (Template) 起到重要作用,提供预测结果的关于三维结构的先验信息&…...

喜报不断!箱讯平台获评2023年上海市促进现代航运服务业创新示范项目

近期,可谓捷报频传!在箱讯科技子公司苏州箱讯获评苏州市软件和信息服务业 “头雁”培育企业没过多久,就又迎来好消息! 日前,上海市交通委发布“2023年上海市促进现代航运服务业创新项目”评选结果,箱讯An…...

SOME/IP学习笔记3

目录 1.SOMEIP Transformer 1.1 SOME/IP on-wire format 1.2 协议指定 2. SOMEIP TP 2.1 SOME/IP TP Header 3.小结 1.SOMEIP Transformer 根据autosar CP 相关规范,SOME/IP Transformer主要用于将SOME/IP格式的数据序列化,相当于一个转换器。总体…...

【ATTCK】ATTCK开源项目Caldera学习笔记

CALDERA是一个由python语言编写的红蓝对抗工具(攻击模拟工具)。它是MITRE公司发起的一个研究项目,该工具的攻击流程是建立在ATT&CK攻击行为模型和知识库之上的,能够较真实地APT攻击行为模式。 通过CALDERA工具,安全…...

黑窗口连接远程服务

ssh root192.168.x.x 回车输入密码 查看docker docker ps 停止正在运行的服务 docker stop xxxxx 删除服务 docker rm xxxxx 查看镜像 docker images 删除镜像 docker rmi xxxxx 删除镜像 启动并运行整个服务 docker compose up -d jar包名称 idea 使用tcp方式连接docker 配置d…...

好消息!2023年汉字小达人市级比赛在线模拟题大更新:4个组卷+11个专项,助力孩子更便捷、有效、有趣地备赛

自从《中文自修》杂志社昨天发通知,官宣了2023年第十届汉字小达人市级比赛的日期和安排后,各路学霸们闻风而动,在自己本就繁忙的日程中又加了一项:备赛汉字小达人市级比赛,11月30日,16点-18点。 根据这几年…...

SAP 70策略测试简介

在前面的文章中我们已经测试了10、11、20、40、50、52、60、62策略的测试,接下来我们需要对70策略进行测试,很多的项目中也都会用到70策略。 70策略是一种比较常见的、基于按库存且主要用于半成品或者原材料的计划策略。 我们还是按照之前的惯例,先看下70策略的后台配置 我…...

uniapp+vue3+ts+vite+echarts开发图表类小程序,将echarts导入项目使用的详细步骤,耗时一天终于弄好了

想在uniapp和vue3环境中使用echarts是一件相当前卫的事情,官方适配的还不是很好,echarts的使用插件写的是有些不太清晰的,这里我花费了一天的时间,终于将这个使用步骤搞清楚了,并且建了一个仓库,大家可以直…...

分布式服务器架构的优点有哪些?

在当今数字化时代,随着互联网的普及和技术的不断进步,企业和组织面临着处理越来越多的数据和用户请求的挑战。为了应对这些挑战,分布式服务器架构应运而生。分布式服务器架构通过将任务和数据分散到多个服务器上,提供了许多优点&a…...

Zephyr-7B论文解析及全量训练、Lora训练

文章目录 一、Zephyr:Direct Distillation of LM Alignment1.1 开发经过1.1.1 Zephyr-7B-alpha1.1.2 Zephyr-7B-beta 1.2 摘要1.3 相关工作1.4 算法1.4.1 蒸馏监督微调(dSFT)1.4.2 基于偏好的AI反馈 (AIF)1.4.3 直接蒸馏偏好优化&…...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目:3442. 奇偶频次间的最大差值 I 思路 :哈希,时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况,哈希表这里用数组即可实现。 C版本: class Solution { public:int maxDifference(string s) {int a[26]…...

树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频

使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...

rknn优化教程(二)

文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...

三维GIS开发cesium智慧地铁教程(5)Cesium相机控制

一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点&#xff1a; 路径验证&#xff1a;确保相对路径.…...

阿里云ACP云计算备考笔记 (5)——弹性伸缩

目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...

JavaScript 中的 ES|QL:利用 Apache Arrow 工具

作者&#xff1a;来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗&#xff1f;了解下一期 Elasticsearch Engineer 培训的时间吧&#xff01; Elasticsearch 拥有众多新功能&#xff0c;助你为自己…...

centos 7 部署awstats 网站访问检测

一、基础环境准备&#xff08;两种安装方式都要做&#xff09; bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats&#xff0…...

(二)TensorRT-LLM | 模型导出(v0.20.0rc3)

0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述&#xff0c;后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作&#xff0c;其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...

使用分级同态加密防御梯度泄漏

抽象 联邦学习 &#xff08;FL&#xff09; 支持跨分布式客户端进行协作模型训练&#xff0c;而无需共享原始数据&#xff0c;这使其成为在互联和自动驾驶汽车 &#xff08;CAV&#xff09; 等领域保护隐私的机器学习的一种很有前途的方法。然而&#xff0c;最近的研究表明&…...

LeetCode - 394. 字符串解码

题目 394. 字符串解码 - 力扣&#xff08;LeetCode&#xff09; 思路 使用两个栈&#xff1a;一个存储重复次数&#xff0c;一个存储字符串 遍历输入字符串&#xff1a; 数字处理&#xff1a;遇到数字时&#xff0c;累积计算重复次数左括号处理&#xff1a;保存当前状态&a…...