基于webgl(threejs)的路面编辑

Posted ITman彪叔

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于webgl(threejs)的路面编辑相关的知识,希望对你有一定的参考价值。

楔子

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

路面对象扩展

简单的路面希望能够通过一个路径来生成。 我们知道在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创建对象的效果如下图所示:

基于webgl(threejs)的路面编辑_3c

路面编辑

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

 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;

)

大概得过程如下所示:

基于webgl(threejs)的路面编辑_建模_02


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

生成连接处

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

// 找到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);

如下图所示:

基于webgl(threejs)的路面编辑_3c_03

结语

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

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

以上是关于基于webgl(threejs)的路面编辑的主要内容,如果未能解决你的问题,请参考以下文章

裂缝识别基于matlab GUI路面裂缝识别含Matlab源码 009期

裂缝识别基于matlab GUI路面裂缝识别含Matlab源码 009期

智享●书推荐基于人工智能的无人驾驶车辆路面识别技术,基于人工智能的无人驾驶车辆路面识别技术 王世峰 等 著

裂缝识别基于matlab GUI BP神经网络路面裂缝识别系统含Matlab源码 1063期

路面分类基于matlab灰度共生矩阵图形纹理检测+SVM路面状况分类含Matlab源码 1519期

路面平整度采集和计算方法