楔子

在很多应用中,特别是一些园区类的应用。 都需要对园区的地面 环境进行展示,路面就是地面的一部分。

通常的做法是,都是建模的时候把相关的元素都建好,然后导入到展示系统中进行展示。

不过有些情况下,可能建模并不太方便,所以三维编辑器可以直接进行简单的路面编辑显得挺有必要。

路面对象扩展

简单的路面希望能够通过一个路径来生成。 我们知道在threejs中有通过路径生成管路的对象,参考文章 WebGL管网展示(及TubeGeometry优化) 管路的横截面是一个圆形。 道路的横截面期望是一个矩形,因此,我们可以仿照管路的思路制作一个类似的对象PathRectGeometry,只是计算顶点的时候,横截面不再使用圆形,而是使用一个矩形,代码如下:

 let points = [new Vec3(-width/2,-height/2,0),new Vec3(-width/2,height/2,0),
new Vec3(width/2,height/2,0),new Vec3(width/2,-height/2,0)]
if(!scope.clockwise) {
points = [new Vec3(-width/2,-height/2,0),new Vec3(width/2,-height/2,0),
new Vec3(width/2,height/2,0),new Vec3(-width/2,height/2,0)];
}
for( let j = 0;j <= points.length;j ++) {
let jj = j == points.length ? 0 : j;
let point = points[jj];
let radius = Math.hypot(point.x,point.y);
const sin = point.y / radius;
const cos = point.x / radius; normal.x = ( cos * N.x + sin * B.x );
normal.y = ( cos * N.y + sin * B.y );
normal.z = ( cos * N.z + sin * B.z );
normal.normalize(); normals.push( 0,1,0 );
// vertex
vertex.x = P.x + radius * normal.x;
vertex.y = P.y + radius * normal.y;
vertex.z = P.z + radius * normal.z; vertices.push( vertex.x, vertex.y, vertex.z );
}

通过PathRectGeometry创建对象的效果如下图所示:

路面编辑

通过在平面上面打点来构建直线和贝塞尔曲线,然后通过构建得线条了生成路径,通过路径就可以生成路面效果,

 graph.getView().addEventListener("click", (event) => {
let now = new Date().getTime();
if (t != 0 && now - t < 500) {
return;
}
t = now;
if (path) {
let pos = graph.getPositionOnPlaneByEvent(event, plane);
constraintsHorizontalOrVertical(path, pos);
path.lineTo(pos.x, pos.y, pos.z);
tempPath = path.clone(tempPath);
tempRoad.geometry.path = tempPath;
}
})

大概得过程如下所示:



在生成得路径上,会有很多控制点,拖动控制点可以二次修改路径:

生成连接处

两条路得连接处会有斑马线之类得,点击生成斑马线,可以通过算法自动计算斑马线,

// 找到road1 到road2的joint
function createJointShape(road1, road2) {
let path = road1.geometry.path;
let path2 = road2.geometry.path;
let lastPoint = path.points.at(-1);
let lastCurve = path.curves.at(-1);
let curves = path2.curves;
console.log(curves);
let minCurve, minDist = Infinity,
minPoint
for (let i = 0; i < curves.length; i++) {
let curve = curves[i];
if (curve.type == "LineCurve3") {
let {
dist,
point
} = findClosestPoint(lastPoint, curve.v1, curve.v2);
if (dist < minDist) {
minDist = dist;
minPoint = point;
minCurve = curve;
}
}
}
console.log(minCurve, minDist, minPoint); let v1 = lastCurve.v1,
v2 = lastCurve.v2;
let tagent = new dt.Vec3().subVectors(v2, v1);
let up = new dt.Vec3(0, 1, 0);
let cross = new dt.Vec3().cross(up, tagent);
cross.normalize();
let halfRoadWidth = 50;
cross.multiplyScalar(halfRoadWidth);
let cross2 = cross.clone().multiplyScalar(3.0); let p1 = lastPoint.clone().add(cross),
p2 = lastPoint.clone().sub(cross); let sub = new dt.Vec3().subVectors(minPoint, lastPoint);
console.log(sub.length(), minDist, halfRoadWidth)
sub.setLength(minDist - halfRoadWidth); let joinPoint = new dt.Vec3().addVectors(lastPoint, sub); let halfSub = sub.clone().multiplyScalar(0.75);
let p3Center = p1.clone().add(halfSub);
let p4Center = p2.clone().add(halfSub); let p3 = joinPoint.clone().add(cross2);
let p4 = joinPoint.clone().sub(cross2) let newPath = new dt.ShapePath(); newPath.moveTo(p2.x, p2.z);
newPath.quadraticCurveTo(p4Center.x, p4Center.z, p4.x, p4.z);
newPath.lineTo(p3.x, p3.z);
newPath.quadraticCurveTo(p3Center.x, p3Center.z, p1.x, p1.z);
// newPath.closePath();
// let geo = new dt.PathTubeGeometry(newPath, 64, 2);
// let tube = new dt.Mesh(geo); let shapePath = newPath; const simpleShapes = shapePath.toShapes(true); var texture = graph.loadTexture("./road/001.jpg", {
wrapT: dt.RepeatWrapping,
wrapS: dt.RepeatWrapping,
});
texture.repeat.set(1 / 100, 1 / 100);
texture.anisotropy = 16; let m1 = new dt.BasicMaterial({
// flatShading:true,
map: texture,
// envMap:envMap,
// reflectivity:0.4,
color: 0xffffff,
toneMapped: false,
}); var geometry = new dt.ExtrudeGeometry(simpleShapes, {
depth: 1,
bevelEnabled: false,
vertical: true,
});
var mesh = new dt.Mesh(geometry, m1);
window.graph.getDataManager().add(mesh); road1.add(mesh);
}

如下图所示:

结语

本文所示只是一个demo级别得尝试,如果要做一个强度得路面编辑器系统,可能要考虑得还有很多,比如多车道效果,更重得衔接形状等等。这在后续得产品中会持续强化相关功能。

如果你有好的思路,也欢迎和我交流。关注公号“ITMan彪叔” 可以添加作者微信进行交流,及时收到更多有价值的文章。

基于webgl(threejs)的路面编辑的更多相关文章

  1. 基于WebGL/Threejs技术的BIM模型轻量化之图元合并

    伴随着互联网的发展,从桌面端走向Web端.移动端必然的趋势.互联网技术的兴起极大地改变了我们的娱乐.生活和生产方式.尤其是HTML5/WebGL技术的发展更是在各个行业内引起颠覆性的变化.随着WebG ...

  2. canvas svg webgl threejs d3js 的区别

    canvas 绘制2D位图. Echarts是基于Canvas技术的可视化工具,底层封装了原生的JavaScript的绘图 API. canvas里面绘制的图形不能被引擎抓取,canvas中我们绘制图 ...

  3. PixiJS - 基于 WebGL 的超快 HTML5 2D 渲染引擎

    Pixi.js 是一个开源的HTML5 2D 渲染引擎,使用 WebGL 实现,不支持的浏览器会自动降低到 Canvas 实现.PixiJS 的目标是提供一个快速且轻量级的2D库,并能兼容所有设备.此 ...

  4. 基于WebGL的三维的物联网平台技术

    参加工作三年了,从一个搞调试的民工进阶为程序员,收获还是有那么一点的.慢慢讲一些. 去年在网上发现了https://hightopo.com/cn-index.html图扑软件的基于WebGL的三维j ...

  5. WPF学习12:基于MVVM Light 制作图形编辑工具(3)

    本文是WPF学习11:基于MVVM Light 制作图形编辑工具(2)的后续 这一次的目标是完成 两个任务. 本节完成后的效果: 本文分为三个部分: 1.对之前代码不合理的地方重新设计. 2.图形可选 ...

  6. WPF学习11:基于MVVM Light 制作图形编辑工具(2)

    本文是WPF学习10:基于MVVM Light 制作图形编辑工具(1)的后续 这一次的目标是完成 两个任务. 画布 效果: 画布上,选择的方案是:直接以Image作为画布,使用RenderTarget ...

  7. 用基于WebGL的BabylonJS来共享你的3D扫描模型

    转自:http://www.geekfan.net/6578/ 用基于WebGL的BabylonJS来共享你的3D扫描模型 杰克祥子 2014 年 2 月 26 日 0 条评论 标签:3D扫描 , B ...

  8. 基于layui,Jquery 表格动态编辑 设置 编辑值为 int 或者 double 类型及默认值

    首先先推荐大家在看这篇笔记时,阅读过我写的这篇 Layui表格编辑[不依赖Layui的动态table加载] 阅读过上面那篇笔记之后呢,才能更好的理解我现在所要说的这个东西 接下来废话不多说,上代码. ...

  9. 基于 webGL 的元素周期表 3D 交互展示

    前言 之前在网上看到别人写的有关元素周期表的文章,深深的勾起了一波回忆,记忆里初中时期背的“氢氦锂铍硼,碳氮氧氟氖,钠镁铝硅磷,硫氯氩钾钙”.“养(氧)龟(硅)铝铁盖(钙),哪(钠)家(钾)没(镁)青 ...

随机推荐

  1. 【网站】windows phpstudy v8.1搭建https

    这两天在搭建微擎,使用了官方推荐的一键安装环境,在搭建完站点后,想开启https. 发现如下图所示,无论关闭网站,还是关闭nginx.都无法建立https.网上也找不到相关流程,后来试着关闭nginx ...

  2. fpn(feature-Pyramid-network)学习笔记

    FPN(特征金字塔网络)学习笔记 论文 在物体检测里面,有限计算量情况下,网络的深度(对应到感受野)与 stride 通常是一对矛盾的东西,常用的网络结构对应的 stride 一般会比较大(如 32) ...

  3. 第06组 Beta冲刺 (3/5)

    目录 1.1 基本情况 1.2 冲刺概况汇报 1.郝雷明 2. 方梓涵 3.曾丽莉 4.杜筱 5. 董翔云 6.黄少丹 7.鲍凌函 8.詹鑫冰 9.曹兰英 10.吴沅静 1.3 冲刺成果展示 1.1 ...

  4. 面试官:Netty心跳检测机制是什么,怎么自定义检测间隔时间?

    哈喽!大家好,我是小奇,一位热爱分享的程序员 小奇打算以轻松幽默的对话方式来分享一些技术,如果你觉得通过小奇的文章学到了东西,那就给小奇一个赞吧 文章持续更新 一.前言 书接上回,昨天在地里干了一天的 ...

  5. Linux下添加MySql组件后报无权限问题解决

    Tomcat日志报错如下: Caused by: java.sql.SQLException: Access denied for user 'root'@'localhost' (using pas ...

  6. 功耗优化之Sensor功耗分析

    功耗优化之Sensor功耗分析 一.Sensor功耗问题分类 二.Sensor功耗问题分析方法 SSC子系统引起系统无法进入AOSD问题分析: SSC子系统频繁唤醒AP问题分析方法 SSC子系统的GP ...

  7. CYaRon!语

    P3695 CYaRon!语 开始之前 上次水了些小模拟之后感觉不能再颓废了,于是就来大模拟. 然后这个题花了我一个多星期 还是最差解 不过,为了纪念我的第 20 道紫题,纪念我这一周的努力,我还是想 ...

  8. numpy中的np.round()取整的功能和注意

    numpy中的np.round()取整的功能和注意 功能 np.round() 是对浮点数取整的一个函数,一般的形式为 np.round(a, b),其中a为待取整的浮点数,b为保留的小数点的位数 注 ...

  9. 数字图像处理-基于matlab-直方图均匀化,傅立叶变换,图像平滑,图像锐化

    直方图均匀化 任务:用MATLAB或VC或Delphi等实现图像直方图均匀化的算法. clc;clear;close all; % 清除工作台 % path(path,'..\pics'); % 设置 ...

  10. 记一次grpc server内存/吞吐量优化

    背景 最近,上线的采集器忽然时有OOM.采集器本质上是一个grpc服务,网络设备通过grpc协议将数据上报后,采集器进行格式等整理后,发往下一个系统(比如分析,存储). 打开运行环境,发现特性如下: ...