使用 three.js 渲染个blender模型

首先需要一个扫描模型,工业上有专门的设备去采集模型的面然后通过建模软件去处理外表面贴图

我们这里取了一个ford汽车的发动机模型

为了让three.js能够使用,使用blender把模型保存为glb格式

为了让页面加载glb模型更快,需要对模型文件进行压缩

压缩 GLB(GL Transmission Format Binary)模型可以通过多种技术来实现,以减少文件大小并提高加载速度。以下是一些常见的方法:

1. 几何数据简化

  • 网格简化:使用工具(如 Blender、MeshLab 或 Simplify3D)简化模型的几何结构,减少多边形数量。
  • LOD(Level of Detail):创建不同细节级别的模型,根据视距加载不同的细节级别。

2. 纹理压缩

  • 纹理分辨率:降低纹理的分辨率,尤其是在模型的细节不明显的部分。
  • 纹理格式:使用压缩纹理格式(如 DDS、KTX 或 ASTC)来减少纹理文件的大小。

3. 使用 Draco 压缩

  • Draco:Google 的 Draco 库可以对 3D 网格进行高效压缩。您可以使用 gltf-pipeline 工具将 GLB 模型与 Draco 压缩结合起来。

    npm install -g gltf-pipeline
    gltf-pipeline -i model.glb -o model-draco.glb -d

ford-engine-model-4.glb 是我压缩后的模型,把压缩好的模型文件放入项目中

这里直接贴代码了, three.js是纯js框架,所以没有用vue和react来集成

<!DOCTYPE html>
<html lang="en">
<head>
	<title>car engine gbl</title>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
	<link type="text/css" rel="stylesheet" href="main.css">
	<style>
		body {
			margin: 0 !important;
		}

		a {
			color: #2fa1d6;
		}

		p {
			max-width: 600px;
			margin-left: auto;
			margin-right: auto;
			padding: 0 2em;
		}

		body #info {
			position: fixed;
			font-size: 22px;
			width: 100%;
			right: 0;
			text-align: left;
		}

		.content-parent {
			padding: 0 40px;
			display: flex;
			justify-content: space-between;
		}

		.content > div {
			display: inline-block;
			font-size: 16px;
			font-weight: bold;
			/* color: tomato; */
		}

		.value {
			font-size: 16px;
			margin-left: 16px;
		}
	</style>
</head>

<body>

<script type="importmap">
			{
				"imports": {
					"three": "../build/three.module.js",
					"three/addons/": "./jsm/"
				}
			}
</script>

<script type="module">
	import * as THREE from 'three';
	import Stats from 'three/addons/libs/stats.module.js';
	import {GUI} from 'three/addons/libs/lil-gui.module.min.js';
	import {GLTFLoader} from 'three/addons/loaders/GLTFLoader.js';
	import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
	import {TransformControls} from 'three/addons/controls/TransformControls.js';
	import { DRACOLoader } from "./jsm/loaders/DRACOLoader.js"

	function getRandomRGBColor() {  
		var r = Math.floor(Math.random() * 256);
		var g = Math.floor(Math.random() * 256);
		var b = Math.floor(Math.random() * 256);
		
		// 如果需要,可以转换为十六进制字符串  
		var hex = '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);  
	
		// 返回RGB对象或十六进制字符串,根据你的需要  
		// return { r, g, b }; // 返回RGB对象  
		return hex; // 返回十六进制字符串  
	}  
  
	// 使用函数
	console.log(getRandomRGBColor());  // 输出类似 #3A72FF 的随机颜色(十六进制字符串)

	let container, stats, clock, gui, mixer, actions, activeAction, orbitControls, transformControls;
	let camera, scene, renderer, model, dracoLoader;
	const OOI = {};

	init();
	

	function init() {
		scene = new THREE.Scene();
		scene.background = new THREE.Color(0xe0e0e0);

		container = document.createElement('div');
		document.body.appendChild(container);

		//camera = new THREE.PerspectiveCamera( 30, window.innerWidth / window.innerHeight, 1, 8000 );
		camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 5000);
		camera.position.set(-40, 35, 50);
		//camera.lookAt( -5, -3, 0 );
		camera.lookAt(scene.position);


		//scene.fog = new THREE.Fog(0xe0e0e0, 20, 100);

		// const axesHelper = new THREE.AxesHelper(5);
		// scene.add(axesHelper);

		clock = new THREE.Clock();
		// lights
		// const hemiLight = new THREE.HemisphereLight( 0xffffff, 0x8d8d8d, 3 );
		// hemiLight.position.set( 0, 20, 0 );
		// scene.add( hemiLight );
		//
		const dirLight = new THREE.DirectionalLight(0xffffff, 8);
		dirLight.position.set(0, 20, 10);
		scene.add(dirLight);

		// ground
		// const mesh = new THREE.Mesh( new THREE.PlaneGeometry( 2000, 2000 ), new THREE.MeshPhongMaterial( { color: 0xcbcbcb, depthWrite: false } ) );
		// mesh.rotation.x = - Math.PI / 2;
		// scene.add( mesh );

		// const grid = new THREE.GridHelper(5, 40, 0x000000, 0x000000);
		// grid.material.opacity = 1;
		// grid.material.transparent = false;
		// scene.add(grid);

		renderer = new THREE.WebGLRenderer({antialias: true});
		renderer.setPixelRatio(window.devicePixelRatio);
		renderer.setSize(window.innerWidth, window.innerHeight);
		container.appendChild(renderer.domElement);
		window.addEventListener('resize', onWindowResize);

		// stats
		// stats = new Stats();
		// container.appendChild(stats.dom);
		dracoLoader = new DRACOLoader()
        // 设置解压路径,draco_decoder.js文件所在位置
		dracoLoader.setDecoderPath("https://www.gstatic.com/draco/v1/decoders/");
		dracoLoader.setDecoderConfig({ type: 'js' });
		dracoLoader.preload();
		const loader = new GLTFLoader();
		loader.setDRACOLoader(dracoLoader);

		loader.load('models/gltf/engine/ford-engine-model-4.glb', function (gltf) {
			model = gltf.scene;
			scene.add(model);
			//createGUI( model, gltf.animations );
			model.traverse(n => {
				if (n.name === 'Scene') OOI.Scene = n
			});
			const targetPosition = OOI.Scene.position.clone();
			orbitControls = new OrbitControls(camera, renderer.domElement);
			orbitControls.minDistance = 30;
			orbitControls.maxDistance = 50;
			orbitControls.enableDamping = false;
			orbitControls.enablePan = false;
			orbitControls.enableRotate = false;
			orbitControls.target.copy(targetPosition);
			// transformControls = new TransformControls(camera, renderer.domElement);
			// transformControls.size = 0.75;
			// transformControls.showX = false;
			// transformControls.showY = false;
			// transformControls.showZ = false;
			// transformControls.space = 'world';
			// transformControls.attach(OOI.Scene);
			// scene.add(transformControls);
			//transformControls.addEventListener('mouseDown', () => orbitControls.enabled = false);
			//transformControls.addEventListener('mouseUp', () => orbitControls.enabled = true);
			let angle = 0;
			const rotationSpeed = 0.0005; // 每帧旋转的角度

			animate = function() {
			  // 围绕 y 轴旋转
			  angle += rotationSpeed;
			  camera.position.x = Math.cos(angle) * orbitControls.minDistance;
			  camera.position.z = Math.sin(angle) * orbitControls.minDistance;
			  camera.lookAt(orbitControls.target);

			  orbitControls.update();
			  renderer.render(scene, camera);
			}
			renderer.setAnimationLoop(animate);

		}, undefined, function (e) {
			console.error(e);
		});
	}

	function fadeToAction(name, duration) {

		activeAction = actions[name];
		if (previousAction !== activeAction) {
			previousAction.fadeOut(duration);
		}
		activeAction
			.reset()
			.setEffectiveTimeScale(1)
			.setEffectiveWeight(1)
			.fadeIn(duration)
			.play();
	}

	function onWindowResize() {
		camera.aspect = window.innerWidth / window.innerHeight;
		camera.updateProjectionMatrix();
		renderer.setSize(window.innerWidth, window.innerHeight);
	}

	//

	function animate() {
		const dt = clock.getDelta();
		if (mixer) mixer.update(dt);
		renderer.render(scene, camera);
		stats.update();
	}

</script>

</body>
</html>

贴一个three.js驱动ford-engine-model-4.glb 的页面效果,实现360°旋转

滚轮事件实现拉近

旋转到背面

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/905366.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

jade 0919 | 提取自TVBox的直播盒子,频道丰富高清

jade电视直播app覆盖央视全频道和各大卫视&#xff0c;各地地方台也能一网打尽&#xff0c;随时随地看高清电视。各卫视台覆盖广泛&#xff0c;包括浙江电视台、湖南卫视、江苏卫视、东方卫视等全部卫视台&#xff0c;最新内容先一步掌握。拥有广东、北京、风云足球等热播体育频…

Oracle视频基础1.3.2练习

1.3.2 看 Oracle 实例是否启动 ps -ef | grep oracle备份已有的数据库文件到 old 文件夹&#xff0c;用 sample pfile 手动创建新的数据库文件 pfile mkdir old,mv * old,ls,cd old,cp init.ora …/initwilson.ora编辑 pfile&#xff0c;修改 db_name&#xff0c;db_block_siz…

“中信同业+”焕新升级 锚定数字金融新主线,做实金融“五篇大文章”

9月20日&#xff0c;“中信同业”升级发布会及生物多样性债券指数发布在京顺利举办&#xff0c;此次活动以“做强数字金融 服务实体经济”为主题&#xff0c;由中信金控指导&#xff0c;中信银行主办&#xff0c;中信各金融子公司联合承办。来自银行、证券、保险、基金等行业百…

重学SpringBoot3-Spring WebFlux之HttpHandler和HttpServer

更多SpringBoot3内容请关注我的专栏&#xff1a;《SpringBoot3》 期待您的点赞&#x1f44d;收藏⭐评论✍ 重学SpringBoot3-Spring WebFlux之HttpHandler和HttpServer 1. 什么是响应式编程&#xff1f;2. Project Reactor 概述3. HttpHandler概述3.1 HttpHandler是什么3.2 Http…

全桥PFC电路及MATLAB仿真

一、PFC电路原理概述 PFC全称“Power Factor Correction”&#xff08;功率因数校正&#xff09;&#xff0c;PFC电路即能对功率因数进行校正&#xff0c;或者说是能提高功率因数的电路。是开关电源中很常见的电路。功率因数是用来描述电力系统中有功功率&#xff08;实际使用…

【音视频 | ADPCM】音频编码ADPCM详细介绍及例子

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; &#x1f923;本文内容&#x1f923;&a…

python读取视频并转换成gif图片

1. 安装三方库 moviepy 将视频转换成gif&#xff0c;需要使用 moviepy库 确保已经安装了moviepy库 pip install moviepy2. 代码实现&#xff1a; from moviepy.editor import VideoFileClipmyclip VideoFileClip("video.mp4") myclip2 myclip.subclip(0, 10).re…

人工智能原理实验二:搜索方法

一、实验目的 本实验课程是计算机、智能、物联网等专业学生的一门专业课程&#xff0c;通过实验&#xff0c;帮助学生更好地掌握人工智能相关概念、技术、原理、应用等&#xff1b;通过实验提高学生编写实验报告、总结实验结果的能力&#xff1b;使学生对智能程序、智能算法等…

在Centos7.9服务器上使用LVM方式挂载磁盘以及Windows磁盘性能测试与Linux磁盘性能测试命令hdparm详细

一、在Centos7.9服务器上使用LVM方式挂载磁盘 在磁盘分区挂载之前&#xff0c;先使用lsblk命令查看磁盘信息&#xff0c;未分区挂载的磁盘sdb只有disk类型没有part类型。40G的硬盘sda已经分了两个区sda1、sda2。而sdb磁盘下并没有分区信息&#xff0c;说明还没有分区。磁盘分区…

dicom基础:乳腺影像方位信息介绍

目录 一、轴位 (CC, Craniocaudal) 二、侧位 (Lateral) 三、侧斜位 (MLO, Mediolateral Oblique) 四、不同的拍摄方位的乳腺影像展示 1、RCC&#xff08;Right Craniocaudal&#xff09; 2、LCC&#xff08;Left Craniocaudal&#xff09; 3、RMLO&#xff08;Right Medio…

uniapp 报错Invalid Host header

前言 在本地使用 nginx 反向代理 uniapp 时&#xff0c;出现错误 Invalid Host header 错误原因 因项目对 hostname 进行检查&#xff0c;发现 hostname 不是预期的&#xff0c;所以&#xff0c;报错 Invalid Host header 。 解决办法 这样做是处于安全考虑。但&#xff0…

10个领先的增强现实平台【AR】

增强现实 (AR) 被描述为一种通过计算机生成的内容增强现实世界的交互式体验。 使用软件、应用程序和硬件&#xff08;例如 AR 眼镜&#xff09;&#xff0c;AR 能够将数字内容叠加到现实环境和物体上。早在 2024 年&#xff0c;许多像 Apple 这样的公司就已进入 VR/AR 市场&am…

匹配——rabin_karp是怎么滚动的?

滚动散列函数 接前面用例公式滚动last_pos第三行第二行第一行证明后话接前面 匹配——散列法里面只说前一个字符乘以128再对72057594037927931求模,答案乘以128加后一个字符再对72057594037927931求模。对应代码: hash_s = (DOMAIN * hash_s + ord(s[i])) % PRIME用例 还是…

国产数据库之Vastbase海量数据库 G100

海量数据库Vastbase是基于openGauss内核开发的企业级关系型数据库。其语法和Oracle数据库很像&#xff0c;基本是从Oracle数据库迁移到海量数据库&#xff0c;以下简单介绍入门的使用 1、建库操作 地址&#xff1a;x.x.x.x root/Qa2021 安装路径&#xff1a;/home/vastbase 创…

进程、孤儿进程、僵尸进程、fork、wait简介

进程相关概念 程序和进程 程序&#xff1a;是指编译好的二进制文件&#xff0c;在磁盘上&#xff0c;占用磁盘空间, 是一个静态的概念. 进程&#xff1a;一个启动的程序&#xff0c; 进程占用的是系统资源&#xff0c;如&#xff1a;物理内存&#xff0c;CPU&#xff0c;终端等…

【万兴科技-注册_登录安全分析报告】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造成亏损无底洞…

【笔记】数据结构与算法

参考链接&#xff1a;数据结构(全) 参考链接&#xff1a;数据结构与算法学习笔记 一些PPT的整理&#xff0c;思路很不错&#xff0c;主要是理解角度吧&#xff0c;自己干啃书的时候结合一下会比较不错 0.总论 1.数据 注&#xff1a;图是一种数据结构&#xff01;&#xff01;…

匿名内部类的理解

这个知识点困惑我很久&#xff0c;前几天面试的时候也问到了&#xff0c;没回答出来 首先先说说使用步骤吧 1.有一个接口&#xff0c;且含有一个抽象方法&#xff08;通常情况我们不会写abstract关键字&#xff0c;冗余的&#xff09; 2.然后有一个外部类&#xff08;Anonymo…

深入探索电能消耗数据:基于机器学习的分析与洞察

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

架构的本质之 MVC 架构

前言 程序员习惯的编程方式就是三步曲。 所以&#xff0c;为了不至于让一个类撑到爆&#x1f4a5;&#xff0c;需要把黄色的对象、绿色的方法、红色的接口&#xff0c;都分配到不同的包结构下。这就是你编码人生中所接触到的第一个解耦操作。 分层框架 MVC 是一种非常常见且常…