我想在我场景中的轴上放置x,y,z标签(精灵)。问题是使用相机进行变焦,也会导致类似地移动粒子,使它们停留在“屏幕”的一侧。
所以我只是想找到一种方法来始终知道x,y,z的线条在相机之外的位置以更新标签的位置: fiddle(这里它们只是静态的)。
我可能需要的伪代码:
function update() {
var pointInLinePosition = calculateLastVisiblePointOfXline();
xSprite.position.set(pointInLinePosition.x, pointInLinePosition.y, pointInLinePosition.z);
}
function calculateLastVisiblePointOfXline(){
}
答案 0 :(得分:0)
我找到了一个足够令人满意的解决方案(至少对我而言)但并不完美。
首先,我使用场景的相机创建了一个平截头体:
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()的返回值来更新标签的位置.trossLine()是交点。
这是更新的小提琴:fiddle
我希望有所帮助。在我的情况下它适合。
答案 1 :(得分:0)
交叉路口的正确测试还必须确保交叉点实际上在截头锥体内,因为截头锥体平面无限延伸,可能导致假阳性交叉点。
验证交叉口的一种天真的方法是检查交叉点到所有平面的距离。如果距离大于或等于零,则该点在平截头体内。
调整后的代码是从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
进行比较以解决浮点舍入错误)