找到一条直线消失后的点 - three.js
Find the point of a line after which it dissapears - three.js
我想在场景中的轴上放置 x、y、z 标签(精灵)。问题是用相机缩放,应该会导致粒子也类似地移动,因此它们会停留在 "screen".
的一侧
所以我只想找到一种方法来始终知道 x、y、z 的线在相机之外的位置以更新标签的位置:
fiddle(这里它们只是静态的)。
我可能需要实现的伪代码:
function update() {
var pointInLinePosition = calculateLastVisiblePointOfXline();
xSprite.position.set(pointInLinePosition.x, pointInLinePosition.y, pointInLinePosition.z);
}
function calculateLastVisiblePointOfXline(){
}
我找到了一个足够令人满意(至少对我而言)但并不完美的解决方案。
首先,我使用场景的相机创建了一个平截头体:
var frustum = new THREE.Frustum();
frustum.setFromMatrix( new THREE.Matrix4().multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse ) );
然后,我检查平截头体的任何平面是否与场景中的任何直线相交:
for (var i = frustum.planes.length - 1; i >= 0; i--) {
var py = frustum.planes[i].intersectLine( new THREE.Line3( new THREE.Vector3(0,0,0), new THREE.Vector3(1000,0,0) ) ) ;
if(py !== undefined) {
ySprite.position.x = py.x-1 ;
}
var px = frustum.planes[i].intersectLine( new THREE.Line3( new THREE.Vector3(0,0,0), new THREE.Vector3(0,0,1000) ) ) ;
if(px !== undefined) {
xSprite.position.z = px.z-1 ;
}
};
如果有交点,我使用交点 intersectLine() 的 return 值更新标签的位置。
这是更新后的 fiddle : fiddle
希望对您有所帮助。就我而言,它适合。
正确的交点测试还必须确保交点实际上在平截头体内,因为平截头体平面无限延伸,可能导致误报交点。
验证交点的一种简单方法是检查交点到所有平面的距离。如果距离大于或等于零,则该点在平截头体内。
从 ThanosSar 的回答中截取的调整后代码:
const intersect = point => frustum.planes
.map(plane =>
plane.intersectLine(new THREE.Line3(new THREE.Vector3(0, 0, 0), point))
)
.filter(sect => sect != null)
.filter(sect => frustum.planes.every(plane => plane.distanceToPoint(sect) >= -0.000001))[0];
const iy = intersect(new THREE.Vector3(1000, 0, 0));
if (iy != null)
ySprite.position.x = iy.x - 1;
const ix = intersect(new THREE.Vector3(0, 0, 1000));
if (ix != null)
xSprite.position.z = ix.z - 1;
(与 >= -0.000001
进行比较以解决浮点舍入误差)
我想在场景中的轴上放置 x、y、z 标签(精灵)。问题是用相机缩放,应该会导致粒子也类似地移动,因此它们会停留在 "screen".
的一侧所以我只想找到一种方法来始终知道 x、y、z 的线在相机之外的位置以更新标签的位置: fiddle(这里它们只是静态的)。
我可能需要实现的伪代码:
function update() {
var pointInLinePosition = calculateLastVisiblePointOfXline();
xSprite.position.set(pointInLinePosition.x, pointInLinePosition.y, pointInLinePosition.z);
}
function calculateLastVisiblePointOfXline(){
}
我找到了一个足够令人满意(至少对我而言)但并不完美的解决方案。
首先,我使用场景的相机创建了一个平截头体:
var frustum = new THREE.Frustum();
frustum.setFromMatrix( new THREE.Matrix4().multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse ) );
然后,我检查平截头体的任何平面是否与场景中的任何直线相交:
for (var i = frustum.planes.length - 1; i >= 0; i--) {
var py = frustum.planes[i].intersectLine( new THREE.Line3( new THREE.Vector3(0,0,0), new THREE.Vector3(1000,0,0) ) ) ;
if(py !== undefined) {
ySprite.position.x = py.x-1 ;
}
var px = frustum.planes[i].intersectLine( new THREE.Line3( new THREE.Vector3(0,0,0), new THREE.Vector3(0,0,1000) ) ) ;
if(px !== undefined) {
xSprite.position.z = px.z-1 ;
}
};
如果有交点,我使用交点 intersectLine() 的 return 值更新标签的位置。
这是更新后的 fiddle : fiddle
希望对您有所帮助。就我而言,它适合。
正确的交点测试还必须确保交点实际上在平截头体内,因为平截头体平面无限延伸,可能导致误报交点。
验证交点的一种简单方法是检查交点到所有平面的距离。如果距离大于或等于零,则该点在平截头体内。
从 ThanosSar 的回答中截取的调整后代码:
const intersect = point => frustum.planes
.map(plane =>
plane.intersectLine(new THREE.Line3(new THREE.Vector3(0, 0, 0), point))
)
.filter(sect => sect != null)
.filter(sect => frustum.planes.every(plane => plane.distanceToPoint(sect) >= -0.000001))[0];
const iy = intersect(new THREE.Vector3(1000, 0, 0));
if (iy != null)
ySprite.position.x = iy.x - 1;
const ix = intersect(new THREE.Vector3(0, 0, 1000));
if (ix != null)
xSprite.position.z = ix.z - 1;
(与 >= -0.000001
进行比较以解决浮点舍入误差)