在 Three.js 中将贝塞尔曲线转换为平面道路

soi*_*ber 5 javascript 3d three.js

我试图根据之前计算得到的一些贝塞尔曲线在 Three.js 中绘制一条弯曲的道路,问题是我找不到转换曲线序列的方法(一条从上一条曲线的末尾开始)到一个曲面。

我有一个 3D 场景,其中有一些汽车、一条用飞机创建的道路,并且绘制了即将到来的道路的路径。我使用我所说的贝塞尔曲线将路径表示为一条线

function createAdasisBezier(initx, inity, cp1x, cp1y, cp2x, cp2y, finalx, finaly) {
  bezier = new THREE.CubicBezierCurve3(
    new THREE.Vector3(initx, inity, 0),
    new THREE.Vector3(cp1x, cp1y, 0),
    new THREE.Vector3( cp2x, cp2y, 0),
    new THREE.Vector3(finalx, finaly, 0)
  );
  curvePath = new THREE.CurvePath();
  curvePath.add(bezier);

  var geoPath = curvePath.createPointsGeometry( 5 );
  var lineMat = new THREE.LineBasicMaterial({color: 0xff0000});

  curveLine = new THREE.Line(geoPath, lineMat);

  curveLine.rotation.set(-Math.PI/2,0,0);
  curveLine.position.y = 0.1;

  scene.add(curveLine);
}
Run Code Online (Sandbox Code Playgroud)

结果就是这个

首先,我尝试挤压这条线,但后来我意识到这可能不是解决方案,因为我想做一条路,尽管我可以移动 X 和 Y 上的顶部顶点,将它们放置在贝塞尔曲线附近,以便成为外部曲线的一部分,结果不仅不利,而且无法保持左右曲线之间的关系。

为了移动顶点(一旦确定),我做了一个循环并手动移动它们:

for (var i = 0; i < geoPath.vertices.length; ++i) {
  geoPath.vertices[i].y += 10;
}
Run Code Online (Sandbox Code Playgroud)

向右移动顶点 拉伸中未启用斜角。

然后我尝试在每个贝塞尔曲线上绘制一个平面(作为它们的子项)并将其旋转以面向路径,但结果并不像我预期的那样,如果是这样,它会破坏曲线的弧线。

为此,我创建了每个贝塞尔曲线的副本,并将其放在原始贝塞尔曲线旁边,然后创建了平面。

 var plane = new THREE.PlaneBufferGeometry(10,25,1,1);
 var planemesh = new THREE.Mesh(plane, material);
 planemesh.position.set(copy.geometry.vertices[0].x, copy.geometry.vertices[0].y, 0);
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

我想做的最后一件事是创建一条线的克隆,将其分开几米,并将一个顶点的第一个顶点“连接”到另一个顶点的第一个顶点,这样我就得到了一个闭合的几何体,并且我可以创建一个面,但我不知道如何“连接”两个不同几何图形的顶点。我尝试将顶点从一个添加到另一个,但没有成功。

有人知道如何将这条线转换成弯曲的道路吗?提前致谢。

Mar*_*zzo 4

您应该尝试查看“几何体”>“拉伸”>“形状”示例。正如您所看到的,所有挤出的形状都保持其宽度和方向,尽管左/右旋转或完全循环。

他们没有使用贝塞尔曲线,而是使用CatmullRomCurve3来定义拉伸。如果你查看源代码,会发现制作红色挤压形状的基本代码从第 69 行开始:

// Define the curve
var closedSpline = new THREE.CatmullRomCurve3( [
    new THREE.Vector3( -60, -100,  60 ),
    new THREE.Vector3( -60,   20,  60 ),
    new THREE.Vector3( -60,  120,  60 ),
    new THREE.Vector3(  60,   20, -60 ),
    new THREE.Vector3(  60, -100, -60 )
] );
closedSpline.type = 'catmullrom';
closedSpline.closed = true;

// Set up settings for later extrusion
var extrudeSettings = {
    steps           : 100,
    bevelEnabled    : false,
    extrudePath     : closedSpline
};

// Define a triangle
var pts = [], count = 3;
for ( var i = 0; i < count; i ++ ) {
    var l = 20;
    var a = 2 * i / count * Math.PI;
    pts.push( new THREE.Vector2 ( Math.cos( a ) * l, Math.sin( a ) * l ) );
}
var shape = new THREE.Shape( pts );

// Extrude the triangle along the CatmullRom curve
var geometry = new THREE.ExtrudeGeometry( shape, extrudeSettings );
var material = new THREE.MeshLambertMaterial( { color: 0xb00000, wireframe: false } );

// Create mesh with the resulting geometry
var mesh = new THREE.Mesh( geometry, material );
Run Code Online (Sandbox Code Playgroud)

从这里开始,只需对这些参数进行一些小的调整即可获得您想要的特定道路形状。

  • 它有效,我真的很感谢你。我之前没有尝试过这个,因为它迫使我更新我的 Qt 版本(它使用 Three.js 的修订版 71,并且与 CatmullRomCurve 不兼容,现在它是 r74,我可以使用那种类型的曲线)有时似乎有除了浪费一点时间更新东西之外别无他法。我向您致以最诚挚的谢意,Marco Del Valle,非常感谢您的快速回复和友善。 (3认同)