正如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,请为您抱歉)
(对于小提琴)放慢动作,测试不需要
requestAnimationFrame
,setTimeout(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/