Three.js高级应用--利用Three.js+WebGL实现fbx和obj格式模型的自定义加载
通过对webgl和three.js的不断学习与实践,在三维应用场景建设过程中,利用Three.js与webgl配合可以实现大部分三维场景的应用需求,这一篇主要讲述如何利用Three.js加载已有的模型,支持的三维模型格式有.fbx和.obj,同时.obj格式记得将对应的mtl文件放在与obj文件同目录下,名称一致即可。这样就可以加载我们已经建设好的各类三维模型,目前100M之内的模型加载都没问题。Three.js的基础代码请参考其他三篇文章,一般利用Three.js实现三维场景的代码主要内容有:
1.获取canvas元素
2.创建场景scene
3.创建相机camera
4.添加相机控件OrbitControls
5.添加灯光-环境光AmbientLight
6.创建渲染器renderer并设置像素比和场景背景色
7.添加三维物体,一般在另一个js中完成。
8.添加动画函数实现场景的动态循环渲染、添加浏览器窗口变化事件,用于设置随着浏览器窗口大小进行画布大小的调整。
开发环境:vue-2.5.2,Three.js-0.142.0,开发工具webstorm2021.2.3, 前端用chrome109.0.5414.120,其他默认。
以下是实现三维模型加载示例的功能描述和关键代码。
一、功能简述:在浏览器中实现已有三维模型文件的动态加载,不需要安装插件,支持旋转、放大缩小、移动,场景扫描和烟雾预警等。
二、实现效果:


三、关键代码如下(相机platform下的src/enter目录下的index.js和addComponent.js文件):
1.index.js文件中需要引入加载各个三维组件对应的js。
import { AddComponent } from './addComponent.js'
export const initPlatform = () => {//添加三维场景的各个组件,相当于加载各种三维模型const plat = new AddComponent(scene, camera, controls);const clock = new THREE.Clock();const start = () => {plat.start(clock.getDelta());//记得更新相机位置controls.update();// 渲染场景renderer.render(scene, camera)requestAnimationFrame(start)}start();//设置随着浏览器窗口大小进行画布大小的调整window.addEventListener('resize', () => {// 更新宽高比camera.aspect = window.innerWidth / window.innerHeight// 更新相机的投影矩阵camera.updateProjectionMatrix()renderer.setSize(window.innerWidth, window.innerHeight)// 设置像素比renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))})
}
2.addComponent.js文件中引入加载模型后的处理js和加载fbx和obj文件的js,每个组件是一个类。
import { SurroundLine } from '../effect/surroundLine.js'
import { loadFBX } from '../utils'
import { loadOBJ } from '../utils'
export class AddComponent {constructor(scene, camera, controls) {this.scene = scene;this.camera = camera;this.controls = controls;this.loadModel('fbx');}// 加载模型,并且渲染到画布上loadModel(fileType) {if(fileType=='fbx'){loadFBX('/src/model/NB352-3D.fbx').then(object => {object.rotation.z = Math.PI / 2;//模型旋转90度object.traverse((child) => {if (child.isMesh) {new SurroundLine(this.scene, child, this.height, this.time);}})this.initEffect();})}else if(fileType=='obj'){loadOBJ('/src/model/factory.obj').then(object => {object.traverse((child) => {if (child.isMesh) {new SurroundLine(this.scene, child, this.height, this.time);}})// this.initEffect();})}}
}
3.surroundLine.js完整文件如下:
import * as THREE from "three";export class SurroundLine {constructor(scene, child, height, time) {this.height = height;this.scene = scene;this.child = child;this.time = time;this.createMesh();}computedMesh() {this.child.geometry.computeBoundingBox();this.child.geometry.computeBoundingSphere();}createMesh() {this.computedMesh();const { max, min } = this.child.geometry.boundingBox// 高度差const size = max.z - min.z//利用webgl原始的顶点和片元着色器对模型进行设置。const material = new THREE.ShaderMaterial({uniforms: {// 当前扫描的高度u_height: this.height,// 扫描线条的颜色是什么u_up_color: {value: new THREE.Color({color:'#5588AA'}),},u_city_color: {// 得需要一个模型颜色 最底部显示的颜色value: new THREE.Color(color.mesh)},u_head_color: {// 要有一个头部颜色 最顶部显示的颜色value: new THREE.Color(color.head)},u_size: {value: size,},u_time: this.time,},//顶点着色器vertexShader: `uniform float u_time;varying vec3 v_position;void main() {// 变化的时间float uMax = 4.0;v_position = position;// 变化的比例float rate = u_time / uMax * 2.0;// 边界条件if (rate > 1.0) {rate = 1.0;}float z = position.z * rate;gl_Position = projectionMatrix * modelViewMatrix * vec4(vec2(position), z, 1.0);}`,//片元着色器fragmentShader: `varying vec3 v_position;uniform vec3 u_city_color;uniform vec3 u_head_color;uniform float u_size;uniform vec3 u_up_color;uniform float u_height;void main() {vec3 base_color = u_city_color;base_color = mix(base_color, u_head_color, v_position.z / u_size);// 上升线条的高度是多少if (u_height > v_position.z && u_height < v_position.z + 6.0) {float f_index = (u_height - v_position.z) / 3.0;base_color = mix(u_up_color, base_color, abs(f_index - 1.0));}gl_FragColor = vec4(base_color, 1.0);}`,})const mesh = new THREE.Mesh(this.child.geometry, material);// 让mesh 继承 child 的旋转、缩放、平移mesh.position.copy(this.child.position)mesh.rotation.copy(this.child.rotation)mesh.scale.copy(this.child.scale)this.scene.add(mesh);}
}
相关文章:
Three.js高级应用--利用Three.js+WebGL实现fbx和obj格式模型的自定义加载
通过对webgl和three.js的不断学习与实践,在三维应用场景建设过程中,利用Three.js与webgl配合可以实现大部分三维场景的应用需求,这一篇主要讲述如何利用Three.js加载已有的模型,支持的三维模型格式有.fbx和.obj,同时.o…...
Go struct
每个无名结构体类型的字面形式均由struct关键字开头,后面跟着用一对大括号{},其中包裹着的一系列字段(field)声明。 一般来说,每个字段声明由一个字段名和字段类型组成。一个结构体类型的字段数目可以为0。struct {tit…...
Redis多线程模型源码解析
1. 配置启用多线程 默认情况下多线程是默认关闭的,如果想要启动多线程,需要在配置文件中做适当的修改。 修改redis.conf 文件如下 io-threads 4 #启用的 io 线程数量 io-threads-do-reads yes #读请求也使用io线程2 源码解析 进入到Redis的main入口函…...
搭建zabbix4.0监控服务实例
一.Zabbix服务介绍 1.1服务介绍 Zabbix是基于WEB界面的分布式系统监控的开源解决方案,Zabbix能够监控各种网络参数,保证服务器系统安全稳定的运行,并提供灵活的通知机制让SA快速定位并解决存在的各种问题。 1.2 Zabbix优点 Zabbix分布式监…...
Xcode 系统崩溃问题01
参考链接:https://www.5axxw.com/questions/content/x2zlpx 问题:崩溃提示: Message from debugger: The LLDB RPC server has crashed. You may need to manually terminate your process. The crash log is located in ~/Library/Logs/Dia…...
SpringMVC文件上传、下载、国际化配置
Java知识点总结:想看的可以从这里进入 目录3.6、文件上传、下载3.6.1、文件上传3.6.2、文件下载3.7、国际化配置3.6、文件上传、下载 3.6.1、文件上传 form 表单想要具有文件上传功能,其必须满足以下 3 个条件。 form 表单的 method 属性必须设置为 p…...
计算机图形学07:有效边表法的多边形扫描转换
作者:非妃是公主 专栏:《计算机图形学》 博客地址:https://blog.csdn.net/myf_666 个性签:顺境不惰,逆境不馁,以心制境,万事可成。——曾国藩 文章目录专栏推荐专栏系列文章序一、算法原理二、…...
UNIX编程--Makefile入门
Makefile 文件命名和规则 文件命名 makefile 或者 Makefile Makefile 规则 一个 Makefile 文件中可以有一个或者多个规则目标 ... : 依赖 ...命令 (shell 命令)...目标:最终要生成的文件,伪目标除外依赖:生成目标所需的文件或是目…...
【数据结构初阶】手撕单链表
目录一.链表概念和结构二.单链表功能的实现1.打印单链表内容2.申请单链表节点3.头插和尾插4.头删和尾删5.单链表查找6.pos位置前后插入7.pos位置删除三.链表面试题剖析一.链表概念和结构 概念:链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素…...
angular中http请求和传值
有关angular传值的相关内容 <number-info[subTitle]"customTitle"[total]"item.ENERGY_RATE %"[subTotal]"item.ENERGY_RATE_DIFF %"[status]"item.ENERGY_RATE_DIFF > 0 ? up : down">在number-info上面,会是一个delon/c…...
VSCode问题记录
20230304 - 0. 引言 这几年的编程方式还真是各种变化,从一开始直接VIM,到后面使用jupyter进行机器学习相关,然后再过渡到vim的形式并加以tmux批量化,最后去年使用了vscode作为IDE。随着工具的变化,那么很多习惯也都随…...
html基础学习
初识HTML HTML: 超文本标记语言 一.HTML的基本结构 根控制标记(头) 头控制标记(头) 标题 标题标记 头控制标记(尾) 网页显示区域(一般要实现的代码都在这里写) </body> 根控制标记(尾) 二.网页的基本标签 标题标签 <h1> 一级标题</h1> <…...
leetcode_贪心算法
贪心算法相关题简单题目455.分发饼干1005.K次取反后最大化的数组和860.柠檬水找零序列问题376.摆动序列法一:贪心法法二:动态规划单调递增的数字简化版本有点难度53.最大子序和贪心算法动态规划134.加油站968.监控二叉树两个维度权衡问题分发糖果406.根据…...
C语言每日一题】——杨氏矩阵
【C语言每日一题】——倒置字符串😎前言🙌杨氏矩阵🙌总结撒花💞😎博客昵称:博客小梦 😊最喜欢的座右铭:全神贯注的上吧!!! 😊作者简介…...
最佳iOS设备管理器imazing 2.16.9官网Mac/Windows下载电脑版怎么下载安装
imazing 2.16.9官网Mac/Windows下载电脑版是款针对苹果设备所打造的管理工具。iMazing为用户提供多种设备管理功能,每一位用户都能以自己的形式管理苹果设备。iMazing与苹果设备连接后,用户就可以轻松传输文件,浏览保存信息等。 应用介绍 iM…...
八大排序算法之堆排序的实现+经典TopK问题
目录 一.堆元素的上下调整接口 1.前言 2.堆元素向上调整算法接口 3.堆元素向下调整算法接口 二.堆排序的实现 1.空间复杂度为O(N)的堆排序(以排升序为例) 思路分析: 代码实现: 排序测试: 时空复杂度分析: 2. 空间复杂度为O(1)的堆排序(以排降序为例) 将数组arr调…...
使用AppSmith(PagePlug )低代码平台快速构建小程序应用实践
文章目录一、入门(一)介绍(二)功能特性(三)体验一下(四)参考教程二、使用Appsmith构建商城微信小程序(一)说明(二)应用配置࿰…...
第52章 短信验证服务和登录的后端定义实现
1 Services.Messages.SmsValidate using Core.Domain.Messages; using Data; using Microsoft.EntityFrameworkCore; namespace Services.Messages { /// <summary> /// 【短信验证服务--类】 /// <remarks> /// 摘要: /// 通过类中的方法成员实…...
谷歌验证码的使用
1. 表单重复提交之验证码 1.1 表单重复提交三种常见情况 提交完表单。服务器使用请求转来进行页面跳转。这个时候,用户按下功能键 F5,就会发起最后一次的请求。造成表单重复提交问题。解决方法:使用重定向来进行跳转用户正常提交服务器&…...
Git学习入门(1)- git的安装与配置
title: git学习(1) - git的安装与配置CSDN: https://blog.csdn.net/jj6666djdbbd?typeblogBlog: https://helloylh.comGithub: https://github.com/luumodtags: gitabbrlink: 12001description: 本文主要讲解了git的安装,配置基本工作date: …...
汽车生产虚拟实训中的技能提升与生产优化
在制造业蓬勃发展的大背景下,虚拟教学实训宛如一颗璀璨的新星,正发挥着不可或缺且日益凸显的关键作用,源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例,汽车生产线上各类…...
python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)
更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...
什么是EULA和DPA
文章目录 EULA(End User License Agreement)DPA(Data Protection Agreement)一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA(End User License Agreement) 定义: EULA即…...
鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/
使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题:docker pull 失败 网络不同,需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...
IT供电系统绝缘监测及故障定位解决方案
随着新能源的快速发展,光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域,IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选,但在长期运行中,例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...
深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南
🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...
DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”
目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...
python报错No module named ‘tensorflow.keras‘
是由于不同版本的tensorflow下的keras所在的路径不同,结合所安装的tensorflow的目录结构修改from语句即可。 原语句: from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后: from tensorflow.python.keras.lay…...
MyBatis中关于缓存的理解
MyBatis缓存 MyBatis系统当中默认定义两级缓存:一级缓存、二级缓存 默认情况下,只有一级缓存开启(sqlSession级别的缓存)二级缓存需要手动开启配置,需要局域namespace级别的缓存 一级缓存(本地缓存&#…...
上位机开发过程中的设计模式体会(1):工厂方法模式、单例模式和生成器模式
简介 在我的 QT/C 开发工作中,合理运用设计模式极大地提高了代码的可维护性和可扩展性。本文将分享我在实际项目中应用的三种创造型模式:工厂方法模式、单例模式和生成器模式。 1. 工厂模式 (Factory Pattern) 应用场景 在我的 QT 项目中曾经有一个需…...
