Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >基于webgl(threejs)的路面编辑

基于webgl(threejs)的路面编辑

作者头像
用户3158888
发布于 2022-09-21 01:49:37
发布于 2022-09-21 01:49:37
1.1K00
代码可运行
举报
运行总次数:0
代码可运行

楔子

在很多应用中,特别是一些园区类的应用。 都需要对园区的地面 环境进行展示,路面就是地面的一部分。 通常的做法是,都是建模的时候把相关的元素都建好,然后导入到展示系统中进行展示。 不过有些情况下,可能建模并不太方便,所以三维编辑器可以直接进行简单的路面编辑显得挺有必要。

路面对象扩展

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 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创建对象的效果如下图所示:

路面编辑

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 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;
        }
      })

大概得过程如下所示:

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

生成连接处

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 找到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级别得尝试,如果要做一个强度得路面编辑器系统,可能要考虑得还有很多,比如多车道效果,更重得衔接形状等等。这在后续得产品中会持续强化相关功能。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-08-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
threejs三维地图大屏项目分享
这是最近公司的一个项目。客户的需求是基于总公司和子公司的数据,开发一个数据展示大屏。 大屏两边都是一些图表展示数据,中间部分是一个三维中国地图,点击中国地图的某个省份,可以下钻到省份地图的展示。 地图上,会做一些数据的标注,信息标牌。 如下图所示:
用户3158888
2022/11/23
4.1K0
threejs三维地图大屏项目分享
基于threejs实现中国地图轮廓动画
目前项目的中国地图是echarts画的,现在这想再次基础上增加一个中国地图描边动画。
星宇大前端
2022/05/06
3.4K0
基于threejs实现中国地图轮廓动画
如何1人5天开发完3D数据可视化大屏
相信从事过数据可视化开发的你对大屏并不陌生,那么开发一个酷炫的大屏一定是很多数据可视化开发者想要做的事情。
ConardLi
2020/10/30
3.7K0
如何1人5天开发完3D数据可视化大屏
webgl(threejs)生成房间楼层
在很多数字孪生项目中,都会涉及到楼层的建模。楼层的建模由于结构繁多,如果都是建模师进行手动建模,工作量会比较大。而楼层本身的结构,可以抽象成可以通过路径构造的对象(这和之前的文章提及的的管路以及道路类似),这方便我们通过代码的方式来生成房间楼层。
用户3158888
2022/09/23
1.9K0
webgl(threejs)生成房间楼层
HTML制作3D樱花漫天飞舞及浪漫信封
作者主页:海拥 作者简介:CSDN全栈领域优质创作者、HDZ核心组成员、蝉联C站周榜前十 HTML5制作3D樱花漫天飞舞及浪漫信封 💕浪漫信封:http://haiyong.site/eluvletter 💌3D樱花漫天飞舞:http://haiyong.site/yinghua 💕 浪漫信封 HTML 内容 <div id="jsi-cherry-container"></div> <section class="container" id="contact" > <form clas
海拥
2021/12/20
1.1K0
HTML制作3D樱花漫天飞舞及浪漫信封
threejs地球、星空、世界轮廓绘制、飞线、坐标涟漪 、旋转动画(上篇)
github仓库地址:https://github.com/RainManGO/3d-earth
星宇大前端
2022/03/09
13K0
threejs地球、星空、世界轮廓绘制、飞线、坐标涟漪 、旋转动画(上篇)
分享CodePen上6个酷炫demo特效
最近创作灵感匮乏, 来 CodePen 上找找灵感, 同时也给同样需要获取灵感的 coder (程序员们)带来一点点想象空间.
徐小夕
2024/01/09
5010
分享CodePen上6个酷炫demo特效
Threejs项目实战之四:实现地图雷达效果
最近事情比较多,今晚难得有空,就抽空完成了一个使用Threejs实现地图雷达扫描效果的程序,下面说下代码实现的原理及核心代码,老规矩,先看下效果图
九仞山
2023/12/30
1.2K0
Threejs项目实战之四:实现地图雷达效果
canvas霓虹爱心
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>canvas霓虹爱心</title> <style> body { background-color: #000; margin: 0; overflow: hidden; background-repeat: no-repeat; } </style> </head> <body> <canva
我不是费圆
2021/12/30
6950
canvas霓虹爱心
如何用2 KB代码实现3D赛车游戏?2kPlus Jam大赛了解一下
几个月前,当我听说传奇 JS1K 游戏编程竞赛将不再举办时,当即把这件事告诉了其他开发者,最后我们决定在 itch 上搞一个 2KB 版的编程竞赛以弥补这一遗憾,我们将其称之为「2kPlus Jam」。这个竞赛的主要目标是制作一个只需要 2KB 压缩文件就可以容纳的游戏。如果你知道一个 3.5 英寸软盘可以存超过 700 个这样的游戏,你也就知道这有多小了。
机器之心
2020/05/06
1.3K0
如何用2 KB代码实现3D赛车游戏?2kPlus Jam大赛了解一下
有手就能学会|ShaderToy系列教程-开发环境配置与介绍
现在这里开个坑,这个系列带着做一下shadertoy的一些案例,这个系列教程大概只能算基础教学(目录在下方),所以这个系列教程没有任何压力,有手就能学会。
keyle
2024/11/01
4970
有手就能学会|ShaderToy系列教程-开发环境配置与介绍
漫天花雨HTML特效+3D相册
HTML特效是指在网页中使用各种技术和代码来实现动态效果的一种方式。这些效果可以是动画、过渡、交互和其他视觉效果。HTML特效可以在不影响网页性能的同时增强用户体验。
淼学派对
2023/10/14
8290
漫天花雨HTML特效+3D相册
WebGL简易教程(十四):阴影
所谓阴影,就是物体在光照下向背光处投下影子的现象,使用阴影技术能提升图形渲染的真实感。实现阴影的思路很简单:
charlee44
2019/12/10
1.9K0
WebGL简易教程(十四):阴影
从关键概念开始,万字带你轻松入门 WebGL
只要理解了 WebGL 背后的概念,学习 WebGL 并没有那么难。很多 WebGL 入门文章并没有介绍这些重要的概念,直接使用 WebGL 复杂的 API 开始渲染图形,很轻松就把入坑文变成了劝退文。这篇文章将会着重讲解这些概念,并一步步探究 WebGL 是如何渲染图片到屏幕的,理解这些重要的概念,将会大大降低学习曲线。
羽月
2022/10/08
2.5K0
从关键概念开始,万字带你轻松入门 WebGL
图形编辑器基于Paper.js教程12:井身结构编辑器,多条完全平行的弯曲线,使用额外平行线来作为弯曲中心线的度量尺
对于弯曲的三条平行线,一开始我以为只需要使用中心线,然后复制两条,一个向右下角平移,一个向左上角平移,就能让三条线实现完全平行,每一处的距离都相等。后来仔细思考后,发现我想错了,因为弯曲处的平行距离是,x移动,y移动的平方根。后来想使用曲线的缩放加上平移来实现三条线段弯曲平行,曲线部分依然无法达到完全平行。
拿我格子衫来
2024/08/06
2400
图形编辑器基于Paper.js教程12:井身结构编辑器,多条完全平行的弯曲线,使用额外平行线来作为弯曲中心线的度量尺
[C++][opencv]基于opencv实现photoshop算法曲线调整
https://download.csdn.net/download/FL1623863129/89632923
云未归来
2025/07/21
820
[C++][opencv]基于opencv实现photoshop算法曲线调整
21.opengl高级-几何着色器
几何着色器可以在顶点发送到着色器之前随意变换。可以这么理解:顶点着色器是接收属性,一般不做过多处理,保持原数据,算是第一层接口层;片元着色器一般处理color;如果想做些特殊处理,通过在中间加一层几何着色器把流程拆碎,分工更细致,达到工程代码高内聚低耦合,拓展性更合理。涉及的知识点不多,下面直接通过实例来说明几何着色器的使用原理
公号sumsmile
2020/07/14
1.2K0
Computational Geometry in Python
This post is a simplified version of the accompanying notebook to chapter 6 of my upcoming book Mastering SciPy. Click anywhere on this box for more information.
周星星9527
2020/11/03
1.3K0
Threejs进阶之十七:Threejs中的Path、Shape和ShapeGeometry类
在实际的应用中,有时候需要我们根据一个二维图形拉伸为三维图形的情况,这就需要我们对Threejs中提供的二维图形相关的类有一个深入的了解,这一节我们就深入的聊一聊Threejs中的Path、Shape和ShapeGeometry类
九仞山
2023/10/14
2.3K0
Threejs进阶之十七:Threejs中的Path、Shape和ShapeGeometry类
【愚公系列】2022年09月 微信小程序-three.js加载3D模型
Three.js 是一款运行在浏览器中的 3D 引擎,你可以用它创建各种三维场景,包括了摄影机、光影、材质等各种对象。
愚公搬代码
2022/09/28
5.6K0
【愚公系列】2022年09月 微信小程序-three.js加载3D模型
推荐阅读
相关推荐
threejs三维地图大屏项目分享
更多 >
领券
一站式MCP教程库,解锁AI应用新玩法
涵盖代码开发、场景应用、自动测试全流程,助你从零构建专属AI助手
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档