学习threejs,将多个网格合并成一个网格

news2024/11/14 17:44:36

👨‍⚕️ 主页: gis分享者
👨‍⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅!
👨‍⚕️ 收录于专栏:threejs gis工程师


文章目录

  • 一、🍀前言
    • 1.1 ☘️THREE.Geometry 几何体
    • 1.2 为什么将多个网格合并成一个网格
  • 二、🍀将多个网格合并成一个网格
    • 1. ☘️实现思路
    • 2. ☘️代码样例


一、🍀前言

本文详细介绍如何基于threejs在三维场景中将多个网格合并成一个网格,亲测可用。希望能帮助到您。一起学习,加油!加油!

1.1 ☘️THREE.Geometry 几何体

THREE.Geometry对原生WebGL中的顶点位置position、顶点法向量normal、顶点颜色color、顶点纹理坐标uv、顶点索引index等顶点数据进行了封装。利用 Vector3 或 Color 存储了几何体的相关 attributes(如顶点位置,面信息,颜色等)比起 BufferGeometry 更容易读写,但是运行效率不如有类型的队列。
构造函数:
Geometry() 构造函数没有任何参数。
属性:
boundingBox:Geometry 的外边界矩形,可以通过 .computeBoundingBox() 进行计算,默认值是 null。
boundingSphere:Geometry 的外边界球形,可以通过 .computeBoundingSphere() 进行计算,默认值是 null。
colors:顶点 colors 队列,与顶点数量和顺序保持一致。该属性用于 Points 、 Line 或派生自 LineSegments 的类。 对于 Meshes,请使用 Face3.vertexColors 函数。如果要标记队列中的数据已经更新,Geometry.colorsNeedUpdate 值需要被设置为 true。
faces:faces 队列。描述每个顶点之间如何组成模型面的面队列。同时该队列保存面和顶点的法向量和颜色信息。如果要标记队列中的数据已经更新,Geometry.elementsNeedUpdate 值需要被设置为 true。
faceVertexUvs:面的 UV 层的队列,该队列用于将纹理和几何信息进行映射。每个 UV 层都是一个 UV 的队列,顺序和数量同面中的顶点相对用。如果要标记队列中的数据已经更新,Geometry.uvsNeedUpdate 值需要被设置为 true。
id:当前 geometry 实例的唯一标识符的数。
isGeometry:用于判断当前类或派生类属于 Geometries。默认值是 true。不应该改变该值,该值用于内部优化。
lineDistances:用于保存线型几何体中每个顶点间距离的。在正确渲染 LineDashedMaterial 时,需要用到该数据。
morphTargets:morph targets 的队列。
morphNormals:一个 morph 法向量的数组。
name:当前几何的可选别名。默认值是一个空字符串。
skinWeights:是一个数组,用于几何体蒙皮的。
skinIndices:是一个数组,用于几何体蒙皮的。
uuid:当前对象实例的 UUID。 该值会被自动分配,请不要修改它。
vertices:vertices 的队列。顶点的队列,保存了模型中每个顶点的位置信息。如果要标记队列中的数据已经更新,.verticesNeedUpdate 值需要被设置为 true。
verticesNeedUpdate:如果顶点队列中的数据被修改,该值需要被设置为 true。
elementsNeedUpdate:如果面队列中的数据被修改,该值需要被设置为 true。
uvsNeedUpdate:如果 UV 队列中的数据被修改,该值需要被设置为 true。
normalsNeedUpdate:如果法向量队列中的数据被修改,该值需要被设置为 true。
colorsNeedUpdate:如果颜色队列或 face3 的颜色数据被修改,该值需要被设置为 true。
groupsNeedUpdate:如果 face3 的 materialIndex 被修改,该值需要被设置为 true。
lineDistancesNeedUpdate:如果 linedistances 队列中的数据被修改,该值需要被设置为 true。

1.2 为什么将多个网格合并成一个网格

当对象的数量非常庞大时,性能就会成为一个瓶颈,因为在组里每个对象还是独立的,需要分别对它们进行渲染和处理,所以数量上来以后性能就会受到很大影响。通过THREE.Geometry的merge方法合并网格,可以极大提升渲染效率。

二、🍀将多个网格合并成一个网格

1. ☘️实现思路

  • 1、初始化renderer渲染器
  • 2、初始化Scene三维场景
  • 3、初始化camera相机,定义相机位置 camera.position.set,设置相机方向camera.lookAt。
  • 4、初始化THREE.AmbientLight环境光源,scene场景加入环境光源,初始化THREE.DirectionalLight平行光源,设置平行光源位置,设置平行光源投影,scene添加平行光源。
  • 5、加载几何模型:创建THREE.AxesHelper坐标辅助工具,scene场景加入THREE.AxesHelper坐标辅助工具。
  • 6、加入gui控制,定义重绘方法redraw,redraw方法通过THREE.Geometry对象的merge方法实现立方体合并。加入controls控制,加入stats监控器,监控帧数信息。

2. ☘️代码样例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>learn39(将多个网格合并成一个网格)</title>
    <script src="lib/threejs/91/three.js"></script>
    <!--<script src="lib/threejs/127/three.js-master/build/three.js"></script>-->
    <!--<script src="lib/threejs/127/three.js-master/examples/js/controls/OrbitControls.js"></script>-->
    <script src="https://johnson2heng.github.io/three.js-demo/lib/js/controls/OrbitControls.js"></script>
    <script src="lib/threejs/127/three.js-master/examples/js/libs/stats.min.js"></script>
    <!--<script src="https://johnson2heng.github.io/three.js-demo/lib/js/libs/stats.min.js"></script>-->
    <script src="lib/threejs/127/three.js-master/examples/js/libs/dat.gui.min.js"></script>
</head>
<style>
    html, body {
        margin: 0;
        height: 100%;
    }

    canvas {
        display: block;
    }
</style>
<body onload="draw()">
</body>
<script>
  var renderer
  var initRender = () => {
    renderer = new THREE.WebGLRenderer({antialias: true})
    renderer.setSize(window.innerWidth, window.innerHeight)
    renderer.shadowMap.enabled = true
    renderer.shadowMap.type = THREE.PCFSoftShadowMap
    document.body.appendChild(renderer.domElement)
  }
  var scene
  var initScene = () => {
    scene = new THREE.Scene()
  }
  var camera
  var initCamera = () => {
    camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000)
    camera.position.set(0, 40, 100)
    camera.lookAt(new THREE.Vector3(0, 0, 0))
  }
  var light
  var initLight = () => {
    scene.add(new THREE.AmbientLight(0x444444))

    light = new THREE.DirectionalLight(0xffffff)
    light.position.set(15, 50, 10)
    light.castShadow = true
    scene.add(light)
  }
  var cubeMaterial = new THREE.MeshLambertMaterial({color: 0x00ff00, transparent: true, opacity: 0.8})
  var addCube = () => {
    var cubeGeometry = new THREE.BoxGeometry(1, 1, 1)
    var cube = new THREE.Mesh(cubeGeometry, cubeMaterial)
    cube.castShadow = true
    cube.position.set(-100 + Math.round(Math.random() * 200), -100 + Math.round(Math.random() * 200), -100 + Math.round(Math.random() * 200))
    return cube
  }
  var gui
  var initGui = () => {
    //声明一个保存需求修改的相关数据的对象
    gui = {
      numberOfObjects: 500, //当前场景中模型的个数
      combined: false, //是否合并模型
      redraw: function () {
        //删除场景内现有的立方体
        var arr = []
        scene.traverse(function (e) {
          if (e instanceof THREE.Mesh) arr.push(e)
        });

        arr.forEach(function (value) {
          scene.remove(value)
        })

        //重新生成立方体
        if (gui.combined) {
          //合并模型,则使用merge方法合并
          var geometry = new THREE.Geometry()
          //merge方法将两个几何体对象或者Object3D里面的几何体对象合并,(使用对象的变换)将几何体的顶点,面,UV分别合并.
          //THREE.GeometryUtils: .merge() has been moved to Geometry. Use geometry.merge( geometry2, matrix, materialIndexOffset ) instead.
          for (var i = 0; i < gui.numberOfObjects; i++) {

            var cube = addCube()
            cube.updateMatrix()
            geometry.merge(cube.geometry, cube.matrix)
          }

          scene.add(new THREE.Mesh(geometry, cubeMaterial))
        }
        else {
          //不合并模型,则直接将模型放入
          for (var i = 0; i < gui.numberOfObjects; i++) {
            scene.add(addCube())
          }
        }
      }
    };
    var datGui = new dat.GUI()
    //将设置属性添加到gui当中,gui.add(对象,属性,最小值,最大值)

    //添加旋转功能
    datGui.add(gui, "numberOfObjects", 0, 50000)
    datGui.add(gui, "combined")
    datGui.add(gui, "redraw")

    gui.redraw()
  }
  var initModel = () => {
    var helper = new THREE.AxesHelper(50)
    scene.add(helper)
  }
  var stats
  var initStats = () => {
    stats = new Stats()
    document.body.appendChild(stats.dom)
  }
  var controls
  var initControls = () => {
    controls = new THREE.OrbitControls(camera, renderer.domElement)
    controls.enableDamping = true
    controls.autoRotate = true
    controls.autoRotateSpeed = 0.5
  }
  var render = () => {
    renderer.render(scene, camera)
  }
  var onWindowResize = () => {
    camera.aspect = window.innerWidth / window.innerHeight
    camera.updateProjectionMatrix()
    render()
    renderer.setSize(window.innerWidth, window.innerHeight)
  }
  var animate = () => {
    render()
    stats.update()
    controls.update()
    requestAnimationFrame(animate)
  }
  var draw = () => {
    initRender()
    initScene()
    initCamera()
    initLight()
    initModel()
    initGui()
    initStats()
    initControls()

    animate()

    window.onresize = onWindowResize
  }
</script>
</html>

效果如下:
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vue3 基于element-plus进行的一个可拖动改变导航与内容区域大小的简单方法

1、先上个截图&#xff1a; 说明&#xff1a;拖动上面的分隔栏就可以实现&#xff0c;改变左右区域的大小。 2、上面的例子来自官网的&#xff1a; Container 布局容器 | Element Plus 3、拖动的效果来自&#xff1a; https://juejin.cn/post/7029640316999172104#heading-1…

7个常用的JavaScript数组操作进阶用法

文章目录 1、查找数组中的最大值方法一&#xff1a;使用 Math.max 和展开运算符方法二:使用 for 循环逐一比较 2、查找数组中的第二大值方法一&#xff1a;排序后取第二大值方法二&#xff1a;遍历找到第二大值 3、去除数组中的重复项4、合并两个有序数组并保持有序5、旋转数组…

前深度学习时代-经典的推荐算法

参考自《深度学习推荐系统》—— 王喆&#xff0c;用于学习记录。 1.协同过滤 “协同过滤”就是协同大家的反馈、评价和意见一起对海量的信息进行过滤&#xff0c;从中筛选出目标用户可能感兴趣的信息的推荐过程。 基于用户相似度进行推荐的协同过滤算法 UserCF 用户相似度…

FPGA学习笔记#6 Vitis HLS For循环的优化(2)

本笔记使用的Vitis HLS版本为2022.2&#xff0c;在windows11下运行&#xff0c;仿真part为xcku15p_CIV-ffva1156-2LV-e&#xff0c;主要根据教程&#xff1a;跟Xilinx SAE 学HLS系列视频讲座-高亚军进行学习 学习笔记&#xff1a;《FPGA学习笔记》索引 FPGA学习笔记#1 HLS简介及…

MTK6833/MT6833(天玑700)安卓核心板_联发科5G智能通讯模块安卓主板定制

天玑700定位主流级&#xff0c;让5G技术惠及所有人。 MT6833采用7nm制程工艺&#xff0c;旨在为大众市场带来先进的5G功能和体验&#xff0c;依托5G双载波聚合技术&#xff08;2CC&#xff09;及双5G SIM卡功能&#xff0c;实现优异的功耗表现及实时连网功能。 CPU部分由2个2…

Spring Boot框架的知识分类技术解析

2 开发技术 2.1 VUE框架 Vue.js&#xff08;读音 /vjuː/, 类似于 view&#xff09; 是一套构建用户界面的渐进式框架。 Vue 只关注视图层&#xff0c; 采用自底向上增量开发的设计。 Vue 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。 2.2 Mysql数据库 …

面试:TCP、UDP如何解决丢包问题

文章目录 一、TCP丢包原因、解决办法1.1 TCP为什么会丢包1.2 TCP传输协议如何解决丢包问题1.3 其他丢包情况&#xff08;拓展&#xff09;1.4 补充1.4.1 TCP端口号1.4.2 多个TCP请求的逻辑1.4.3 处理大量TCP连接请求的方法1.4.4 总结 二、UDP丢包2.1 UDP协议2.1.1 UDP简介2.1.2…

关于我、重生到500年前凭借C语言改变世界科技vlog.17——字符函数字符串函数

文章目录 1.字符函数1.1 字符分类函数1.1.1 islower 1.2 字符转换函数1.2.1 tolower 2.字符串函数2.1 strlen2.2 strcpy和strncpy2.3 strcat和strncat2.4 strcmp和strncmp2.5 strstr2.6 strtok2.7 strerror 希望读者们多多三连支持小编会继续更新你们的鼓励就是我前进的动力&am…

可视化建模与UML《类图实验报告》

史铁生&#xff1a; 余华和莫言扛着我上火车&#xff0c; 推着走打雪仗&#xff0c; 还带我偷西瓜&#xff0c; 被人发现后他们拔腿就跑&#xff0c; 却忘了我还在西瓜地里。 一、实验目的&#xff1a; 1、熟悉类图的构件事物。 2、熟悉类之间的泛化、依赖、聚合和组合关系…

基于梧桐数据库的实时数据分析解决方案

一、背景 在当今信息时代&#xff0c;数据的价值不言而喻。然而&#xff0c;处理海量数据并将其转化为有意义的洞察力是一项艰巨的任务。传统的数据处理方法已经无法满足我们日益增长的需求。为了满足这一挑战&#xff0c;实时数据处理系统应运而生。 ​ 实时数据处理系统是一…

javascript实现国密sm4算法(支持微信小程序)

概述&#xff1a; 本人前端需要实现sm4计算的功能&#xff0c;最好是能做到分多次计算。 本文所写的代码在现有sm4的C代码&#xff0c;反复测试对比计算过程参数&#xff0c;成功改造成sm4的javascript代码&#xff0c;并成功验证好分多次计算sm4数据 测试平台&#xff1a; …

jmeter常用配置元件介绍总结之jsr223执行python脚本

系列文章目录 安装jmeter jmeter常用配置元件介绍总结之jsr223执行python脚本 1.安装jsr223执行python插件2.基础语法介绍2.1.log2.2.parameters向脚本传参与接参2.3.vars2.4.props2.5.prev 3.常用脚本3.1.MD5加密单个参数&#xff1a;3.2.MD5加密多个参数&#xff1a;3.3.URLe…

【MongoDB】MongoDB的聚合(Aggregate、Map Reduce)与管道(Pipline) 及索引详解(附详细案例)

文章目录 MongoDB的聚合操作&#xff08;Aggregate&#xff09;MongoDB的管道&#xff08;Pipline操作&#xff09;MongoDB的聚合&#xff08;Map Reduce&#xff09;MongoDB的索引 更多相关内容可查看 MongoDB的聚合操作&#xff08;Aggregate&#xff09; 简单理解&#xff…

快速了解SpringBoot 统一功能处理

拦截器 什么是拦截器&#xff1a; 拦截器是Spring框架提供的重要功能之一&#xff0c;主要进行拦截用户请求&#xff0c;在指定方法前后&#xff0c;根据业务需求&#xff0c;执行预先设定的代码。 也就是说,允许开发⼈员提前预定义⼀些逻辑,在⽤⼾的请求响应前后执⾏.也可以…

百兆网络变压器在无人机系统起到什么作用

华强盛电子 导读&#xff1a; 百兆网络变压器&#xff08;通常指的是100M Ethernet Transformer&#xff09;在无人机系统中扮演着重要的角色&#xff0c;尤其是在网络通信和电气隔离方面 1.电气隔离 网络变压器通过提供电气隔离&#xff0c;帮助保护无人机的电子设备免受电流…

在双显示器环境中利用Sunshine与Moonlight实现游戏串流的同时与电脑其他任务互不干扰

我和老婆经常会同时需要操作家里的电脑&#xff0c;在周末老婆有时要用电脑加班上网办公&#xff0c;而我想在难得的周末好好地Game一下&#xff08;在客厅用电视机或者平板串流&#xff09;&#xff0c;但是电脑只有一个&#xff0c;以往我一直都是把电脑让给老婆&#xff0c;…

【Vue】Vue3.0(十七)Vue 3.0中Pinia的深度使用指南(基于setup语法糖)

上篇文章&#xff1a; 【Vue】Vue3.0&#xff08;十一&#xff09;Vue 3.0 中 computed 计算属性概念、使用及示例 &#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f916;Vue专栏&#xff1a;点击&#xff01; ⏰️创作时间&#xff1a;2024年11月10日15点23分 文章…

深度学习基础练习:从pytorch API出发复现LSTM与LSTMP

2024/11/5-2024/11/7&#xff1a; 前置知识&#xff1a; [译] 理解 LSTM(Long Short-Term Memory, LSTM) 网络 - wangduo - 博客园 【官方双语】LSTM&#xff08;长短期记忆神经网络&#xff09;StatQuest_哔哩哔哩_bilibili 大部分思路来自于&#xff1a; PyTorch LSTM和LSTMP…

【芯智雲城】Sigmastar星宸科技图传编/解码方案

一、图传技术简介 图传是指将图像或媒体内容从一个设备传输到另外一个设备的技术&#xff0c;传输的媒介可以是无线电波、光纤、以太网等。图传系统主要由图像采集设备、传输设备和接收设备组成&#xff0c;图像采集设备负责采集实时图像&#xff0c;传输设备将采集到的图像转…

JavaFX史上最全教程 - Shape - JavaFX矩形椭圆

avaFX Shape类定义了常见的形状&#xff0c;如线&#xff0c;矩形&#xff0c;圆&#xff0c;Arc&#xff0c;CubicCurve&#xff0c;Ellipse和QuadCurve。 在场景图上绘制矩形需要宽度&#xff0c;高度和左上角的&#xff08;x&#xff0c;y&#xff09;位置。 要在JavaFX中…