前言

管路展示在三维场景中很常见。比如地下管网,建筑里面的水果,暖通管道等等的展示。



建立管路的方式主要两种:

  • 通过3DMax C4D Blender等建模工具进行建模。
  • 通过路径数据,程序生成三维管路。

如果需要动态的通过数据生成管路,只能采用第二种方式来生成。

生成管路的方式

在THREE中,通过TubeGeometry可以生成管路。

TubeGeometry可以沿着一条三维样条曲线拉伸出一根管子。可以通过指定顶点来定义路径。创建TubeGeometry管道几何体时可输入以下参数:

  • path(必填)该属性用一个THREE.SplineCurve对象来指定管道遵循的路径
  • segments 该属性指定管道的分段数,路径越长指定的段数应该越多,默认值是64
  • radius 该属性指定管道的半径,默认值是1
  • radiusSegments 否 该属性指定管道截面的分段数,段数越多管道看上去越光滑,默认值是8
  • closed
  • 该属性来设置管道是否收尾连接,默认值false

比如:

const points = [{
x: 0,
y: 0,
z: 0
},
{
x: 100,
y: 0,
z: 0
},
{
x: 100,
y: 0,
z: 200
},
]; const path = createPath(points); const pipeGeometry = new THREE.TubeGeometry(path, 256, radius, 64);
const pipeMaterial = new THREE.MeshPhongMaterial({
color
});
const pipe = new THREE.Mesh(pipeGeometry, pipeMaterial);

效果如下:

TubeGeometry的优化

TubeGeometry 通过指定一个path路径和分段数来创建管路的几何数据。TubeGeometry的分段是平均分配,这会导致一个问题,如果路径很长很复杂,分段数量需要需要很大才能保证几何体的准确性。 然而,管路大部分都是直线,只有少量的弯曲的管路。 如果一条直线管路,其实只需取路径的起始点和介绍点就可以对路径进行完整的描述,只有弯曲的管路,才需要把路径分成很多端,分别取每一个分段点的数据,才能较好的完成曲线的描述。 如果采用平均分段的方式,势必有很多分段落在直线的部分,导致资源的浪费,同时分段数量要求高,创建的几何数据会比较庞大臃肿,影响程序的加载、绘制效率、显存等等。 比如,以下系列点都组成两条直线:

const points = [{
x: 0,
y: 0,
z: 0
},
{
x: 100,
y: 0,
z: 0
},
{
x: 100,
y: 0,
z: 200
},
];

分段数是4的时候:

new THREE.TubeGeometry(path, 4, radius, 64);

得到的是如下结果:

本来两段直线,变成了3段直线的效果,原因就是分片数量不够:

增加分段数:

new THREE.TubeGeometry(path, 256, radius, 64);

效果如下:

为了绘制两条直线组成的路径,需要256的分段数量,顶点数量可想而知。

所以我们可以有一种优化思路,对于路径的直线部分,不需要分段,只需要去起始点和终点即可,分段数只分配给曲线的部分。 这样的分段方式,可以是分段的数量得到最合理的应用。 基于此,我们改造出一个新的类:PathTubeGeometry。

改造后的类,绘制上述两条直线,不需要分片数(分片数量为1),如下:

new PathTubeGeometry(path, 1, radius, 64);

极大的节约了资源。

拐角弯管

两条直线连接的地方,可以通过加上一点圆角的效果来增加管路的美观度,通过下面代码可以自动根据已有路径生成带弯管的路径。

 function getRoundCornerPath(oldPath, radius, path = new Path3D()) {
let points = oldPath.points;
points = removeDup(points);
let p0 = points[0];
path.moveTo(p0);
for (let i = 1; i < points.length - 1; i++) {
let pre = points[i - 1],
p = points[i],
next = points[i + 1];
let sub1 = p.clone().sub(pre).setLength(radius),
sub2 = next.clone().sub(p).setLength(radius);
let v1 = p.clone().sub(sub1),
v2 = p.clone().add(sub2);
path.lineTo(v1);
path.curveTo(p.x, p.y, p.z, v2.x, v2.y, v2.z);
}
let pl = points[points.length - 1];
path.lineTo(pl);
return path;
}

结语

关注公号“ITMan彪叔” 可以添加作者微信进行交流,及时收到更多有价值的文章。

WebGL管网展示(及TubeGeometry优化)的更多相关文章

  1. django学习-27.admin管理后台里:对列表展示页面的数据展示进行相关优化

    目录结构 1.前言 2.完整的操作步骤 2.1.第一步:查看ModelAdmin类和BaseModelAdmin类的源码 2.2.第二步:查看表animal对应的列表展示页面默认的数据展示 2.3.第 ...

  2. WebGL射线拾取模型——八叉树优化

    经过前面2篇WebGL射线拾取模型的文章,相信大家对射线和模型面片相交的原理已经有所了解,那么今天我们再深入探究关于射线拾取的一个问题,那就是遍历场景中的所有与射线相交的模型的优化问题.首先我们来复习 ...

  3. 详细介绍如何计算两条折线的交点并使用Echarts展示以及图表优化

    1.背景 前段时间公司有个需求,需要在一个图表中展示两条折线,并且绘制出两条线的交点.为了满足需求大哥的需求,我也是着实想了有一会.下面我就把具体的实现过程给大家展示一下. 1.1.ECharts 简 ...

  4. 利用GeoWebCache实现WebGIS地形图展示的缓存优化

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/. 1.前言 在WebGIS中,影像金字塔是一个很重要的概念.在WebGI ...

  5. 如何花样展示自己的摄影作品?强大的WebGL能力展示

    注意:Windows平台推荐使用Edge.Chrome.FireFox,部分浏览器打不开 P.S.慢慢用鼠标在图片上拖拽会感觉更神奇    

  6. 基于webgl(threejs)的路面编辑

    楔子 在很多应用中,特别是一些园区类的应用. 都需要对园区的地面 环境进行展示,路面就是地面的一部分. 通常的做法是,都是建模的时候把相关的元素都建好,然后导入到展示系统中进行展示. 不过有些情况下, ...

  7. 如何用webgl(three.js)搭建一个3D库房-第一课

    今天我们来讨论一下如何使用当前流行的WebGL技术搭建一个库房并且实现实时有效交互 第一步.搭建一个3D库房首先你得知道库房长啥样,我们先来瞅瞅库房长啥样(这是我在网上找的一个库房图片,百度了“库房” ...

  8. MySQL优化实例

    这周就要从泰笛离职了,在公司内部的wiki上,根据公司实际的项目,写了一些mysql的优化方法,供小组里的小伙伴参考下,没想到大家的热情很高,还专门搞了个ppt讲解了一下. 举了三个大家很容易犯错的地 ...

  9. H5移动前端性能优化

    在移动端,因手机的配置和3/4G网络的原因,从两个方面解决性能优化问题,1.加载不超过3秒,用loading或者资源不要超过1M.2.渲染速度. 基于以上两个方面,所有影响首屏加载和渲染的代码应在处理 ...

  10. H5移动端性能优化

    概述 1. PC优化手段在Mobile侧同样适用 2. 在Mobile侧我们提出三秒种渲染完成首屏指标 3. 基于第二点,首屏加载3秒完成或使用Loading 4. 基于联通3G网络平均338KB/s ...

随机推荐

  1. Chrome:用uBlacklist屏蔽CSDN搜索结果

    CSDN现在广告满天飞,且很多博客需要先关注才能复制,非常令人无语.如果每次用Google搜索的时候都要加上"-csdn"选项,就非常麻烦.有没有更方便的办法呢?我们可以利用Chr ...

  2. 解密Prompt系列30. LLM Agent之互联网冲浪智能体

    这一章我们介绍能自主浏览操作网页的WebAgent们和相关的评估数据集,包含初级任务MiniWoB++,高级任务MIND2WEB,可交互任务WEBARENA,多模态WebVoyager,多轮对话Web ...

  3. .NetCore 3.1 教程之 EFCore连接Mysql DBFirst模式 从数据库生成实体

    一:创建EF的类库,同时将此项目设置为启动项(为Scaffold-DbContext -tables指令使用),同时安装2个包   ①Microsoft.EntityFrameworkCore.Too ...

  4. Swift Lazy计算属性的线程安全分析

    一.代码示例 // // ViewController.swift // LazyTest // // Created by lilun.ios on 2021/7/30. // import UIK ...

  5. IDEA顺序启动多个Spring Boot微服务

    上个月公司新开发的一个项目,需要使用微服务,将单体服务拆分成多个微服务.但是每次修改代码之后都需要启动多个微服务,改个代码,都要修改五分钟,启动半小时,但是idea可以设置将多个服务依次启动,减少操作 ...

  6. monaco-editor 实现SQL编辑器

    原文链接:https://www.yuque.com/sxd_panda/antv/editor 安装 yarn add monaco-editor 或 npm install monaco-edit ...

  7. INFINI Labs 产品更新 | Console 告警中心 UI 全新改版,新增 Dashboard 全屏模式等功能

    本次 INFINI Labs 产品更新主要发布 Console v1.7.0,重点优化了 Console 告警中心和数据看板 Dashboard 可视化功能.详细介绍如下: 优化告警中心 UI 上个版 ...

  8. koishi-跨平台、可扩展、高性能的机器人

    koishi 介绍 Koishi 是一个跨平台.可扩展.高性能的聊天机器人框架. 它的名字和图标设计来源于东方 Project 中的角色 古明地恋 (Komeiji Koishi).古明地恋是一个会做 ...

  9. C程序函数调用&系统调用

    理解程序的执行 我们要知道CPU可以自由地访问寄存器.内存.另外,程序是由操作系统执行的,所以操作系统能够控制程序的所有执行情况,限制程序的行为. 程序地执行过程: 程序是一个二进制文件,包含程序的代 ...

  10. vue中退出循环的方法

    forEachforEach不能使用break和continue.return也无法退出循环. 使用break,会报错(报错信息:SyntaxError: Illegal break statemen ...