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】使用Playwright断言方法验证网页和Web应用程序状态
作为测试框架,Playwright 提供了一系列断言方法,您可以使用它们来验证网页和 Web 应用程序的状态。在这篇博客中,田辛老师将介绍 Playwright 中可用的各种断言方法,并为每种方法提供示例。 assert page.url() expected_url &…...

libgdx导入blender模型
具体就是参考 官网 https://libgdx.com/wiki/graphics/3d/importing-blender-models-in-libgdx blender 教程可以看八个案例教程带你从0到1入门blender【已完结】 这里贴一下过程图。 1.初始环境搭建略过。 2.打开blender 选中摄像机和灯光,右键进行删除。 3.选中…...

【20230227】回溯算法小结
回溯法又叫回溯搜索法,是搜索的一种方式。回溯法本质是穷举所有可能。如果想让回溯法高效一些,可以加一些剪枝操作。回溯算法解决的经典问题:组合问题切割问题子集问题排列问题棋盘问题如何去理解回溯法?回溯法解决的问题都可以抽…...

centos安装rocketmq
centos安装rocketmq1 下载rocketmq二进制包2 解压二进制包3 修改broker.conf4 修改runbroker.sh和runserver.sh的JVM参数5 启动NameServer和Broker6 安装rockermq dashboard(可视化控制台)1 下载rocketmq二进制包 点击rocketmq二进制包下载地址,下载完成之后通过ft…...

汇编语言程序设计(二)之寄存器
系列文章 汇编语言程序设计(一) 寄存器 在学习汇编的过程中,我们经常需要操作寄存器,那么寄存器又是什么呢?它是用来干什么的? 它有什么分类?又该如何操作?… 你可能会有许多的…...

华为OD机试Golang解题 - 单词接龙 | 独家
华为Od必看系列 华为OD机试 全流程解析+经验分享,题型分享,防作弊指南)华为od机试,独家整理 已参加机试人员的实战技巧华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为机试题 | 机试宝典文章目录 华为Od必看系列使用说明本期题目…...

Elasticsearch的搜索命令
Elasticsearch的搜索命令 文章目录Elasticsearch的搜索命令数据准备URI Searchq(查询字符串)analyzer(指定查询字符串时使用的分析器)df(指定查询字段)_source(指定返回文档的字段)s…...

为什么人们宁可用Lombok,也不把成员设为public?
目录专栏导读一、从零了解JavaBean1、基本概念2、JavaBean的特征3、JavaBean的优点二、定义最简单的JavaBean三、思考一个问题,为何属性是private,然后用get/set方法?四、下面系统的分析以下,why?五、不和谐的声音,禁…...

【Redis】Redis 如何实现分布式锁
Redis 如何实现分布式锁1. 什么是分布式锁1.1 分布式锁的特点1.2 分布式锁的场景1.3 分布式锁的实现方式2. Redis 实现分布式锁2.1 setnx expire2.2 set ex px nx2.3 set ex px nx 校验唯一随机值,再删除2.4 Redisson 实现分布式锁1. 什么是分布式锁 分布式锁其实…...

C++ 断言
文章目录前言assertstatic_assert前言 断言(Assertion)是一种常用的编程手段,用于排除程序中不应该出现的逻辑错误。它是一种很好的Debug工具。其作用是判断表达式是否为真。C提供了assert和static_assert来进行断言。在C库中也有断言,其中断言与C的相同…...