convert bezier into a plane road in three.js

时间:2017-08-04 12:06:05

标签: javascript 3d three.js

I am trying to draw a curved road in three.js from some beziers I get with previous calculations, the problem is that I can't find the way to convert the sequence of curved lines (one starting at the end of the previous one) to a curved plane.

I have a 3D scene where there are some cars, a road created with a plane and the path of the coming road is painted. I use that Bezier curves I said to represent the path as a Line with

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);
}

The result is this one

First, I tried extruding the line, but then I realized that it might not be the solution because I wanted to do a road, and although I could move top vertices on X and Y to place them near the bezier in order to be the external part of the curve, the result was not only unfavourable, it also made impossible to preserve a relation between a left and a right curve.

To move vertices (once identified) I did a loop and move them manually:

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

Moving vertices right Bevel is not enabled in the extude.

Then I tried to draw a plane over each bezier (as a child of them) and rotate it to face the path, but the result was not as I expected, and it if it were, it would spoil the arcs of the curves.

To do it, I created a copy of every bezier, and place it aside the original ones, then I created the plane.

 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);

enter image description here

Last thing I was trying to do is creating a clone of the line, separate it some meters and "connect" the first vertex from one, to the first of the other, so I get a closed geometry, and I can create a Face, but I don't find how to "connect" vertices from 2 different geometries. I tried adding the vertex from one to the other, but it did not work.

Does anybody have an idea how could I convert the line into a curved road? Thanks in adcance.

1 个答案:

答案 0 :(得分:2)

您应该尝试查看Geometry > Extrude > Shapes示例。如您所见,尽管左/右转动或完全环绕,但所有挤压形状都保持其宽度和方向。

他们不是使用贝塞尔曲线,而是使用CatmullRomCurve3来定义拉伸。如果你看一下source code,那么制作红色挤压形状的基本代码就在第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 );

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