正如this answer中的建议,我创建了一个线性插值曲线,如下所示:

THREE.Linear3 = THREE.Curve.create(

  function ( points, label /* array of Vector3 */) {

    this.points = (points == undefined) ? [] : points;
    this.label = label;

  },

  function ( t ) {
    var v = new THREE.Vector3();
    var c = [];
    var points = this.points, point, intPoint, weight;
    point = ( points.length - 1 ) * t;

    intPoint = Math.floor( point );
    weight = point - intPoint;

    c[ 1 ] = intPoint;
    c[ 2 ] = intPoint  > points.length - 2 ? points.length - 1 : intPoint + 1;

    var pt1 = points[ c[1] ],
      pt2 = points[ c[2] ];

    v.copy( pt1 ).lerp( pt2, weight );

    return v;

  }

);


但是,当我尝试显示不同长度的轨迹时(以动画的方式显示),我得到以下行为,即,代替通过点的曲线,它切入了空间,请注意,在以下示例中每个轨迹都应该经过每个球体的坐标(下面的动画gif):



我不确定我是否了解getPoint函数或它应该返回的内容。任何帮助是极大的赞赏。

JSFiddle

这是一个最小的示例,但是您可以看到随着管的扩展,右上角如何出现抖动。

http://jsfiddle.net/ElDeveloper/3uyf3sq3/1/

最佳答案

清理一些代码

那帮助我调查了这个问题。


您正在泄漏几何图形,需要从场景中删除网格后再处理几何图形

scene.remove(c_mesh)
c_tube && c_tube.dispose();

使用WebGLRenderer。 CanvasRenderer leaks removed objects,并且您正在每个帧上创建新对象。 (如果由于某些原因而无法使用CanvasRenderer,请为您抱歉)
(对于小提琴)放慢动作,测试不需要requestAnimationFramesetTimeout(animate, 500);允许用户查看正在发生的事情。
0段管的意义是什么?

if (index >= points.length - 1){
    index = 1; //start with 2 points
}



按预期工作


TubeGeometry执行N(在构造函数中为第二个参数,在Fiddle中为16)段的管。 (我稍后再讲,但我认为您并不总是想要16个细分)
Curve.getPoinAt(TubeGeometry和许多其他几何可能使用的方法)的默认行为是返回等距点。您可以期望:distance(getPointAt(0),getPointAt(0.1)) == distance(getPointAt(0.1),getPointAt(0.2))是真实的。
由于这些点,无论您在路径中放置多少点,TubeGeometry都将构建一个16段管,其所有段的长度均相同,从路径的第一点到最后一点。 15个中间点之一几乎不可能恰好位于边的位置。那应该解释你所看到的。


试图修复的东西


首先摆脱TubeGeometry + Path的等距方式。重载getUtoTmapping应该足够了(我发现阅读源代码):

THREE.Linear3.prototype.getUtoTmapping = function(u) {
    return u;
};

我更改了您的getPoint。它可能做同样的事情,但是我对自己的代码更加满意

function ( t ) {
    var points = this.points;
    var index = ( points.length - 1 ) * t;
    var floorIndex = Math.floor(index);
    if(floorIndex == points.length-1)
        return points[floorIndex];
    var floorPoint = points[floorIndex];
    var ceilPoint = points[floorIndex+1];
    return floorPoint.clone().lerp(ceilPoint, index - floorIndex);
}

将正确的段数提供给TubeGeometry构造函数:

var pathPoints = points.slice(0, index);
c_path = new THREE.Linear3(pathPoints, 'Test');
c_tube = new THREE.TubeGeometry(c_path, pathPoints.length-1, 10, 16, false, true);


在这一点上,您应该大致期望
您应该看到管始终穿过边缘。您还应该看到TubeGeometry不是要有角度的。您可以通过查看TubeGeometry和Curve处理切线的方式来改善此角度问题,或者(如果您不关心慢度)将段数增加到非常大的数目来改善此角度问题:

c_tube = new THREE.TubeGeometry(c_path, 200/*pathPoints.length-1*/, 10, 16, false, true);





这就是答案。您可以在这里找到我实验的最新版本:http://jsfiddle.net/dqn73m98/5/。您还可以询问three.js开发人员是否存在这样的功能,或者在github问题中请求实现(如果有空的话),here

关于javascript - 自定义THREE.Curve.create显示不正确,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25085061/

10-10 00:13