`GeometryCompressionUtils` 是 Three.js 的一个实用工具模块,用于几何体的压缩处理。以下是其主要方法、属性以及对应的输入参数和输出结果的详细说明。

demo案例

在这里插入图片描述

GeometryCompressionUtils 是 Three.js 的一个实用工具模块,用于几何体的压缩处理。以下是其主要方法、属性以及对应的输入参数和输出结果的详细说明。

方法

  1. compressPositions

    • 描述:压缩顶点位置数据以减少内存使用。
    • 输入参数
      • mesh: 要压缩位置数据的 THREE.Mesh 对象。
    • 输出:无返回值,直接修改传入的 mesh 对象。
    GeometryCompressionUtils.compressPositions(mesh);
    
  2. compressNormals

    • 描述:压缩法线数据。
    • 输入参数
      • mesh: 要压缩法线数据的 THREE.Mesh 对象。
      • method: 压缩方法,可能的值包括 'DEFAULT', 'OCT1Byte', 'OCT2Byte', 'ANGLES'
    • 输出:无返回值,直接修改传入的 mesh 对象。
    GeometryCompressionUtils.compressNormals(mesh, 'OCT1Byte');
    
  3. compressUvs

    • 描述:压缩 UV 数据。
    • 输入参数
      • mesh: 要压缩 UV 数据的 THREE.Mesh 对象。
    • 输出:无返回值,直接修改传入的 mesh 对象。
    GeometryCompressionUtils.compressUvs(mesh);
    

示例代码

以下是一个完整的示例代码,展示如何使用 GeometryCompressionUtils 模块对几何体进行压缩处理:

import * as THREE from 'three';
import * as GeometryCompressionUtils from 'three/addons/utils/GeometryCompressionUtils.js';

// 创建场景、相机和渲染器
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

// 创建一个几何体和材质
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshNormalMaterial();
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);

// 设置相机位置
camera.position.z = 5;

// 压缩顶点位置
GeometryCompressionUtils.compressPositions(mesh);

// 压缩法线
GeometryCompressionUtils.compressNormals(mesh, 'OCT1Byte');

// 压缩 UV 数据
GeometryCompressionUtils.compressUvs(mesh);

// 渲染循环
function animate() {
  requestAnimationFrame(animate);
  renderer.render(scene, camera);
}
animate();

主要属性

GeometryCompressionUtils 主要是作为一个工具库,没有特定的属性。其功能通过一组静态方法提供,所有方法均为静态方法。

注意事项

  • 压缩方法应根据具体需求选择。例如,法线压缩方法有多种,应根据性能和精度要求选择合适的方法。
  • 压缩操作会修改传入的几何体数据,因此在压缩之前最好保留原始数据的备份。

GeometryCompressionUtils 提供了一组高效的工具,用于减少几何体在 GPU 上的内存使用,从而提高渲染性能。



<!DOCTYPE html>
<html lang="en">
	<head>
		<title>three.js webgl - buffergeometry - compression</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">
	</head>
	<body>
		<div id="info">
			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> - BufferGeometry Compression<br />
			Octahedron and Quantization encoding methods from Tarek Sherif
		</div>

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

		<script type="module">

			// 导入three.js及其附加库中的必要模块
			import * as THREE from 'three';
			import Stats from 'three/addons/libs/stats.module.js';
			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
			import * as GeometryCompressionUtils from 'three/addons/utils/GeometryCompressionUtils.js';
			import * as BufferGeometryUtils from 'three/addons/utils/BufferGeometryUtils.js';
			import { TeapotGeometry } from 'three/addons/geometries/TeapotGeometry.js';
			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';

			const statsEnabled = true;

			let container, stats, gui;

			let camera, scene, renderer, controls;

			const lights = [];

			// 选项
			const data = {
				'model': 'Icosahedron', // 模型类型
				'wireframe': false, // 是否显示线框
				'texture': false, // 是否使用纹理
				'detail': 4, // 细节等级
				'QuantizePosEncoding': false, // 是否使用位置量化编码
				'NormEncodingMethods': 'None', // 法线编码方法
				'DefaultUVEncoding': false, // 是否使用默认UV编码
				'totalGPUMemory': '0 bytes' // GPU内存总量
			};
			let memoryDisplay;

			// 几何参数
			const radius = 100;

			// 材质
			const lineMaterial = new THREE.LineBasicMaterial( { color: 0xaaaaaa, transparent: true, opacity: 0.8 } );
			const meshMaterial = new THREE.MeshPhongMaterial( { color: 0xffffff, side: THREE.DoubleSide } );

			// 纹理
			const texture = new THREE.TextureLoader().load( 'textures/uv_grid_opengl.jpg' );
			texture.wrapS = THREE.RepeatWrapping;
			texture.wrapT = THREE.RepeatWrapping;
			texture.colorSpace = THREE.SRGBColorSpace;

			// 初始化场景、相机、渲染器、控制器、灯光等
			init();
			animate();

			function init() {
				// 创建一个div容器用于渲染器
				container = document.createElement( 'div' );
				document.body.appendChild( container );

				// 设置渲染器
				renderer = new THREE.WebGLRenderer( { antialias: true } );
				renderer.setPixelRatio( window.devicePixelRatio );
				renderer.setSize( window.innerWidth, window.innerHeight );
				container.appendChild( renderer.domElement );

				// 创建一个新场景
				scene = new THREE.Scene();

				// 设置相机
				camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 1000 );
				camera.position.setScalar( 2 * radius );

				// 设置相机的轨道控制器
				controls = new OrbitControls( camera, renderer.domElement );
				controls.enablePan = false;
				controls.enableZoom = false;

				// 添加环境光到场景中
				scene.add( new THREE.AmbientLight( 0xffffff, 0.3 ) );

				// 设置方向光
				lights[ 0 ] = new THREE.DirectionalLight( 0xffffff, 2.5 );
				lights[ 1 ] = new THREE.DirectionalLight( 0xffffff, 2.5 );
				lights[ 2 ] = new THREE.DirectionalLight( 0xffffff, 2.5 );

				lights[ 0 ].position.set( 0, 2 * radius, 0 );
				lights[ 1 ].position.set( 2 * radius, - 2 * radius, 2 * radius );
				lights[ 2 ].position.set( - 2 * radius, - 2 * radius, - 2 * radius );

				scene.add( lights[ 0 ] );
				scene.add( lights[ 1 ] );
				scene.add( lights[ 2 ] );

				// 添加坐标轴辅助器到场景中
				scene.add( new THREE.AxesHelper( radius * 5 ) );

				// 创建并添加初始几何体到场景中
				let geom = newGeometry( data );
				const mesh = new THREE.Mesh( geom, meshMaterial );
				scene.add( mesh );

				const lineSegments = new THREE.LineSegments( new THREE.WireframeGeometry( geom ), lineMaterial );
				lineSegments.visible = data.wireframe;
				scene.add( lineSegments );

				// 设置用于用户交互的GUI
				gui = new GUI();
				gui.width = 350;

				function newGeometry( data ) {
					// 根据选定的模型创建新几何体
					switch ( data.model ) {
						case 'Icosahedron':
							return new THREE.IcosahedronGeometry( radius, data.detail );
						case 'Cylinder':
							return new THREE.CylinderGeometry( radius / 1.5, radius / 1.5, radius, data.detail * 6 );
						case 'Teapot':
							return new TeapotGeometry( radius / 1.5, data.detail * 3, true, true, true, true, true );
						case 'TorusKnot':
							return new THREE.TorusKnotGeometry( radius / 2, 10, data.detail * 30, data.detail * 6, 3, 4 );
					}
				}

				function generateGeometry() {
					// 生成新几何体并更新场景
					geom = newGeometry( data );
					updateGroupGeometry( mesh, lineSegments, geom, data );
				}

				function updateLineSegments() {
					// 更新线框的可见性
					lineSegments.visible = data.wireframe;
				}

				// 添加文件夹和控件到GUI
				let folder = gui.addFolder( '场景' );
				folder.add( data, 'model', [ 'Icosahedron', 'Cylinder', 'TorusKnot', 'Teapot' ] ).onChange( generateGeometry );
				folder.add( data, 'wireframe', false ).onChange( updateLineSegments );
				folder.add( data, 'texture', false ).onChange( generateGeometry );
				folder.add( data, 'detail', 1, 8, 1 ).onChange( generateGeometry );
				folder.open();

				folder = gui.addFolder( '位置压缩' );
				folder.add( data, 'QuantizePosEncoding', false ).onChange( generateGeometry );
				folder.open();

				folder = gui.addFolder( '法线压缩' );
				folder.add( data, 'NormEncodingMethods', [ 'None', 'DEFAULT', 'OCT1Byte', 'OCT2Byte', 'ANGLES' ] ).onChange( generateGeometry );
				folder.open();

				folder = gui.addFolder( 'UV压缩' );
				folder.add( data, 'DefaultUVEncoding', false ).onChange( generateGeometry );
				folder.open();

				folder = gui.addFolder( '内存信息' );
				folder.open();
				memoryDisplay = folder.add( data, 'totalGPUMemory', '0 bytes' );
				computeGPUMemory( mesh );

				// 如果启用了统计信息,则将统计面板添加到容器中
				if ( statsEnabled ) {
					stats = new Stats();
					container.appendChild( stats.dom );
				}

				// 添加窗口大小调整事件监听器
				window.addEventListener( 'resize', onWindowResize );
			}

			// 处理窗口大小调整事件
			function onWindowResize() {
				renderer.setSize( window.innerWidth, window.innerHeight );
				camera.aspect = window.innerWidth / window.innerHeight;
				camera.updateProjectionMatrix();
			}

			// 动画场景
			function animate() {
				requestAnimationFrame( animate );
				renderer.render( scene, camera );
				if ( statsEnabled ) stats.update();
			}

			// 更新组几何体
			function updateGroupGeometry( mesh, lineSegments, geometry, data ) {
				// 首先处理旧的几何体
				lineSegments.geometry.dispose();
				mesh.geometry.dispose();
				mesh.material.dispose();
				if

 ( data.texture ) mesh.material = new THREE.MeshBasicMaterial( { map: texture } );
				else mesh.material = meshMaterial;

				// 如果启用了位置量化编码
				if ( data.QuantizePosEncoding ) GeometryCompressionUtils.setAttributeNormalized( geometry, geometry.attributes.position );

				// 法线编码方法处理
				switch ( data.NormEncodingMethods ) {
					case 'DEFAULT':
						GeometryCompressionUtils.setAttributeEncoded( geometry, geometry.attributes.normal );
						break;
					case 'OCT1Byte':
						GeometryCompressionUtils.setAttributeEncoded( geometry, geometry.attributes.normal, 1 );
						break;
					case 'OCT2Byte':
						GeometryCompressionUtils.setAttributeEncoded( geometry, geometry.attributes.normal, 2 );
						break;
					case 'ANGLES':
						GeometryCompressionUtils.setAttributeEncoded( geometry, geometry.attributes.normal, 0, GeometryCompressionUtils.EncodingMethod.ANGLES );
						break;
					case 'None':
					default:
						break;
				}

				// 默认UV编码处理
				if ( data.DefaultUVEncoding ) GeometryCompressionUtils.setAttributeEncoded( geometry, geometry.attributes.uv );

				// 更新几何体和线框几何体
				mesh.geometry = geometry;
				lineSegments.geometry = new THREE.WireframeGeometry( geometry );

				// 计算GPU内存使用量
				computeGPUMemory( mesh );
			}

			// 计算GPU内存使用量
			function computeGPUMemory( mesh ) {
				const info = renderer.info;
				const memory = info.memory.geometries + info.memory.textures;
				data.totalGPUMemory = memory + ' bytes';
				memoryDisplay.updateDisplay();
			}

		</script>
	</body>
</html>

压图地址

image.png

一个功能强大的图片处理工具,它可以满足用户对于图片压缩、格式转换、质量调节以及长图片分割等多种需求。

【轻松压缩,一键搞定】您的图片处理神器来了!

压图地址

本内容来源于小豆包,想要更多内容请跳转小豆包 》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小豆包3D世界

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值