首页/新闻资讯/正文详情

Three.js 几何合并教程

发布时间:2026/9/23 2:17:18 来源:云帆数科 栏目:资讯中心
Three.js 几何合并教程
几何合并 ·Geometry Merge· ▶ 在线运行案例案例合集三维可视化功能案例threehub.cn开源仓库github地址https://github.com/z2586300277/three-cesium-examples400个案例代码:网盘链接你将学到什么glTF/FBX/OBJ 外部模型加载相机交互控制器实时阴影 ShadowMap天空盒与环境贴图requestAnimationFrame 渲染循环效果说明本案例演示几何合并效果基于 WebGL 实现「几何合并」可视化效果附完整可运行源码核心用到 OrbitControls、glTF/Draco。建议先打开文首在线案例查看动态画面再对照下方源码逐步理解。核心概念Loader异步加载模型glTF 返回gltf.scene加载后注意scale与坐标系。Draco 需配置DRACOLoader。OrbitControls轨道旋转缩放开enableDamping时每帧需controls.update()。阴影四步renderer.shadowMap.enabled、光源castShadow、物体castShadow、地面receiveShadow。CubeTexture六面贴图作scene.backgroundscene.environment供 PBR 材质反射。实现步骤搭建 Scene / Camera / Renderer 与 OrbitControlsLoader 异步加载模型/纹理资源rAF 循环中 update 并 render代码要点import * as THREE from threeimport { OrbitControls } from three/examples/jsm/controls/OrbitControls.js import { GLTFLoader } from three/examples/jsm/loaders/GLTFLoader.js import { DRACOLoader } from three/examples/jsm/loaders/DRACOLoader.js import * as BufferGeometryUtils from three/examples/jsm/utils/BufferGeometryUtils.js// 基础场景设置 const box document.getElementById(box) const scene new THREE.Scene() const camera new THREE.PerspectiveCamera(75, box.clientWidth / box.clientHeight, 0.1, 1000000) camera.position.set(5, 5, 5)// 渲染器设置 const renderer new THREE.WebGLRenderer({ antialias: true, alpha: true, logarithmicDepthBuffer: true }) renderer.setSize(box.clientWidth, box.clientHeight) renderer.setPixelRatio(window.devicePixelRatio * 2) renderer.shadowMap.enabled true renderer.shadowMap.type THREE.PCFSoftShadowMap box.appendChild(renderer.domElement)// 控制器 const controls new OrbitControls(camera, renderer.domElement) controls.enableDamping true// 光源 scene.add(new THREE.AmbientLight(0xffffff, 3))// 响应式调整 window.onresize () { renderer.setSize(box.clientWidth, box.clientHeight) camera.aspect box.clientWidth / box.clientHeight camera.updateProjectionMatrix() }// 动画循环 function animate() { renderer.render(scene, camera) controls.update() requestAnimationFrame(animate) } animate()// 几何体合并函数 function mergeModelGeometries(model, options {}) { const { material new THREE.MeshStandardMaterial({ color: 0x666666, metalness: 0.5, roughness: 0.5, polygonOffset: true, polygonOffsetFactor: 1.0, polygonOffsetUnits: 1.0 }), ignoreHidden true, mergeThreshold 1e-4 } options; model.updateWorldMatrix(true, true); // 收集网格 const meshes []; model.traverse(object { if (object.isMesh object.geometry (!ignoreHidden || object.visible)) { meshes.push(object); } }); if (meshes.length 0) return null; // 找出共有属性 const commonAttribs new Set(); let refGeom null; meshes.forEach(mesh { const geom mesh.geometry; if (!refGeom) { refGeom geom; Object.keys(geom.attributes).forEach(name commonAttribs.add(name)); } else { for (const name of [...commonAttribs]) { if (!geom.attributes[name]) commonAttribs.delete(name); } } }); if (!commonAttribs.has(position)) commonAttribs.add(position); try { // 预处理几何体 const geometries meshes.map(mesh { const geom mesh.geometry.clone(); commonAttribs.forEach(name { if (!geom.attributes[name]) { if (name normal) { geom.computeVertexNormals(); } else if (name ! position) { const itemSize refGeom.attributes[name].itemSize; geom.setAttribute(name, new THREE.BufferAttribute( new Float32Array(geom.attributes.position.count * itemSize), itemSize )); } } }); Object.keys(geom.attributes).forEach(name { if (!commonAttribs.has(name)) geom.deleteAttribute(name); }); geom.applyMatrix4(mesh.matrixWorld); return geom; }); const mergedGeometry BufferGeometryUtils.mergeGeometries(geometries); if (mergeThreshold 0 mergedGeometry.mergeVertices) { mergedGeometry.mergeVertices(mergeThreshold); } return new THREE.Mesh(mergedGeometry, material); } catch (error) { console.error(模型合并失败:, error); return null; } }// 文件地址 const urls [0, 1, 2, 3, 4, 5].map(k (FILE_HOST files/sky/skyBox0/ (k 1) .png));const textureCube new THREE.CubeTextureLoader().load(urls);new GLTFLoader().setDRACOLoader(new DRACOLoader().setDecoderPath(FILE_HOST js/three/draco/)).load(FILE_HOST files/model/LittlestTokyo.glb, gltf {const mergedModel mergeModelGeometries(gltf.scene, { material: new THREE.MeshStandardMaterial({ metalness: 1, roughness: 0, envMap: textureCube, polygonOffset: true, polygonOffsetFactor: 1.0, polygonOffsetUnits: 1.0 }) }) if (mergedModel) { scene.add(mergedModel);console.log(模型合并成功:, mergedModel); // 调整相机视角 const box new THREE.Box3().setFromObject(mergedModel); const size box.getSize(new THREE.Vector3()).length(); const center box.getCenter(new THREE.Vector3()); camera.near size * 0.01; camera.far size * 100; camera.position.set(center.x, center.y, center.z size * 1.5); camera.lookAt(center); controls.target.copy(center); camera.updateProjectionMatrix(); } });完整源码GitHub小结本文提供几何合并完整 Three.js 源码与在线 Demo建议先运行案例再改 uniform/参数做二次实验更多 Three.js 实战案例见 three-cesium-examples 合集 与 GitHub 开源仓库

相关推荐

COM3D2实时编辑器终极指南:5分钟掌握女仆数据修改技巧
COM3D2实时编辑器终极指南:5分钟掌握女仆数据修改技巧

COM3D2实时编辑器终极指南:5分钟掌握女仆数据修改技巧 【免费下载链接】COM3D2.MaidFiddler Maid Fiddler for COM3D2 -- a real-time value editor for COM3D2 项目地址: https://gitcode.com/gh_mirrors/co/COM3D2.MaidFiddler COM3D2.MaidFiddler是一款专… · 2026/9/17 9:14:41

国内接入Claude Code失败的真正原因与稳定配置方案
国内接入Claude Code失败的真正原因与稳定配置方案

1. 为什么国内开发者接入 Claude 不是“连不上”,而是“连错了”? “Unable to connect to anthropic services: failed to connect to api.anthropic.com”——这行报错,几乎成了国内开发者第一次启动 claude 命令时的“成人礼”。但真相是… · 2026/9/21 9:09:08

2026免费AI IDE实战指南:Trae、Cursor、Cline核心差异与选型逻辑
2026免费AI IDE实战指南:Trae、Cursor、Cline核心差异与选型逻辑

1. 为什么2026年“免费AI编程IDE”突然成了硬需求:从开发节奏断裂点说起我上个月帮一个做智能硬件创业的团队重构他们的Arduino固件开发流程。他们用的是传统VS Code PlatformIO组合,写个WiFi连接状态机要手动查三份文档、反复烧录验证、调试串口日志像… · 2026/9/1 5:23:57

SaaS在线培训系统选型指南:从功能架构到落地实践
SaaS在线培训系统选型指南:从功能架构到落地实践

我先说个真实经历。前年帮一家连锁零售企业选在线培训系统,对方培训负责人上来就问“便宜的有哪些”,结果我拉了一张对比表,从私有化部署、开源系统、SaaS订阅三个方向列了十几款产品。最后他们选了一款SaaS版产品,不是因为功能最… · 2026/9/23 2:17:14

轻速云SaaS在线培训系统拆解:防作弊、课程分配与费用选型指南
轻速云SaaS在线培训系统拆解:防作弊、课程分配与费用选型指南

先说一个很多HR和培训负责人常问我的问题:市面上打“SaaS在线培训系统”旗号的产品少说几十款,真正拉开差距的不是功能数量,而是功能背后的管理逻辑和落地细节。这篇文章我把轻速云从头到尾拆一遍,从账号权限、考试防作弊、课程分… · 2026/9/23 2:17:14

长沙智能家居避坑指南:从协议选型到施工验收全解析
长沙智能家居避坑指南:从协议选型到施工验收全解析

1. 长沙智能家居的现实:先搞懂你是哪种用户在长沙问“智能家居哪家强”,十个人能给你十种答案。有人刚被精装房自带的智能门锁折腾得够呛,有人被朋友家全屋智能的丝滑体验种草,还有人装了一半发现预算翻倍、施工方失联。作为一个在… · 2026/9/23 2:17:14

3步吃透兔子尾巴cd压缩器底层逻辑与最佳实践
3步吃透兔子尾巴cd压缩器底层逻辑与最佳实践

3步吃透兔子尾巴cd压缩器底层逻辑与最佳实践 别再对着那几百页的官方文档发呆,抓不住重点真的会让人想摔键盘。 很多转行入行的朋友一上来就啃源码,结果绕在参数配置里出不来。… · 2026/9/23 2:17:14

图吧工具箱2026重构版实测:硬件检测与C盘清理全攻略
图吧工具箱2026重构版实测:硬件检测与C盘清理全攻略

1. 图吧工具箱到底是什么,为什么2026年还值得装第一次接触图吧工具箱的人,多半是在装机或者电脑出问题的时候被朋友安利的。简单说,它就是一个把几十款硬件检测、系统维护、跑分烤机工具打包在一起的合集软件,装一个等于装了一整排… · 2026/9/23 2:17:14

飞书知识库成员移除实战:lark-cli `wiki +member-remove` 命令详解与源码原理
飞书知识库成员移除实战:lark-cli `wiki +member-remove` 命令详解与源码原理

飞书知识库成员移除实战:lark-cli wiki member-remove 命令详解与源码原理 【免费下载链接】cli The official Lark/飞书 CLI tool, maintained by the larksuite team — built for humans and AI Agents. Covers core business domains including Messenger, Docs… · 2026/9/23 2:17:08

3招搞定手机怎么下载微信面试难题实战项目解析
3招搞定手机怎么下载微信面试难题实战项目解析

3招搞定手机怎么下载微信面试难题实战项目解析 面试被问“手机怎么下载微信”背后的原理,90%的人答不上来。别笑,这看似弱智的问题,实则是考察你对移动应用分发机制、安全校验及网络协议理解的试金石。我带过不少校招新人,他们背了八股文,却连一个A… · 2026/9/23 0:00:03

你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型
你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型

你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型 面试被问“高并发下如何保证消息不丢失”,你张口就是“用Redis”,结果面试官追问“如果Redis宕机了怎么办”,你瞬间卡壳。这种场景太常见了,很多新手在背八股文时,只记住了技术名词… · 2026/9/23 0:00:29

Win7无线热点配置工具源码解析:解决API失效的3个实战技巧
Win7无线热点配置工具源码解析:解决API失效的3个实战技巧

Win7无线热点配置工具源码解析:解决API失效的3个实战技巧 Win7无线热点配置工具在Win10/11上跑不动?不是你的问题,是版本升级后 API 全变了。很多老项目里的 netsh wlan… · 2026/9/23 0:00:36

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码