根据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函数或它应该返回什么。非常感谢任何帮助。
这是一个最小的例子,但你可以看到当管扩展时右角有一个不平稳的动作。
答案 0 :(得分:2)
这帮助我调查了这个问题。
您正在泄漏几何图形,需要在从场景中删除网格后处理几何图形
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管(构造函数中的第二个参数,小提琴中的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