我希望有人可以帮助我。在three.js中,我在位于(0,0,0)位置的SphereGeometry中创建了一个摄像头。我在球体的墙上投射出一幅全景图像。
我正在尝试在threejs框架之外创建一些交互式JS元素,这些元素根据摄像头所面向的方向触发。我有两个参数,theta& amp; phi,它是x&的360度旋转角度。 z和y& z,分别沿着图像。这个概念是,如果那个点(或矢量)在摄像机的视图中,它将触发一些JS事件。请注意,该点不是对象,而是任意一组旋转角度。此外,使用鼠标或设备方向移动相机。换句话说,我不想以编程方式将相机移动到这些点,而是只有在手动旋转相机并且点进入视图时才执行JS。
最初,我开始使用Frustums.containsPoint方法,但意识到我可能并不是真的在寻找空间中的特定点,而是相机角度。我想也许使用camera.getWorldDirection()或者camera.rotation可以提供正确的天使,但我似乎被困在这里。
非常感谢任何帮助。
答案 0 :(得分:0)
将您想要交互性的区域定义为圆锥(方向vec3 +角度),并且每当相机旋转时,检查相机前方dir是否在圆锥内。
答案 1 :(得分:0)
显然,纬度/经度角已经被捕获并存储在每个mousemove事件中,如下所示:
function onDocumentMouseMove( event )
{
if ( isUserInteracting === true && !isControlInteraction )
{
lon = (( onPointerDownPointerX - event.clientX ) * 0.1 + onPointerDownLon) % 360;
lat = (( event.clientY - onPointerDownPointerY ) * 0.1 + onPointerDownLat) % 360;
}
}
然后我可以使用lat / lon变量来计算某个点p的θ/ phi偏移量。如果偏移量小于某个指定半径,例如30度,则可以考虑在范围内。
var v_theta = THREE.Math.degToRad(lat);
var v_phi = THREE.Math.degToRad(lon);
var p_theta = THREE.Math.degToRad(p[0]);
var p_phi = THREE.Math.degToRad(p[1]);
v_theta = Math.atan2(Math.sin(v_theta), Math.cos(v_theta));
v_phi = Math.atan2(Math.sin(v_phi), Math.cos(v_phi));
p_theta = Math.atan2(Math.sin(p_theta), Math.cos(p_theta));
p_phi = Math.atan2(Math.sin(p_phi), Math.cos(p_phi));
var theta_offset = Math.abs(v_theta - p_theta) * 180 / Math.PI;
var phi_offset = Math.abs(v_phi - p_phi) * 180 / Math.PI;
if ( theta_offset <= radius && phi_offset <= radius )
{
// execute some code here
}
但是,这不包括独立工作的设备方向控制事件。我想我现在所处的位置是如何从设备方向计算纬度/经度。我能够获得相机的旋转和位置,但不知道如何从相机旋转矢量中获取lat / lon。
答案 2 :(得分:0)
window.addEventListener( 'deviceorientation', function(e) {
e.preventDefault();
var angle = window.orientation;
if ( angle == null ) return;
var dir = camera.getWorldDirection();
var d_phi = Math.acos( dir.y );
var d_theta = Math.atan2( dir.x, dir.z );
d_theta = Math.atan2(Math.sin(d_theta), Math.cos(d_theta));
// update lat / lon
lon = 90 - THREE.Math.radToDeg(d_phi);
lat = THREE.Math.radToDeg(d_theta);
});
现在,唯一的解决方案是补偿相机的旋转,我一直遇到麻烦。在threejs中,似乎在iOS上,当您第一次加载页面时,世界方向向量与摄像机的旋转对齐,然后只有window.orientation角度发生变化。因此,原始方向似乎影响位置/旋转。如果我希望图像的中心为(0,0),以下似乎适用于iOS,但我不确定这是否正确。
var d_theta = Math.atan2( dir.x, dir.z );
if ( init_orient === 0 ) d_theta = Math.PI - d_theta;
else if ( init_orient == -90 ) d_theta = -Math.PI/2 - d_theta;
else if ( init_orient == 90 ) d_theta = Math.PI/2 - d_theta;
d_theta = Math.atan2(Math.sin(d_theta), Math.cos(d_theta));
不幸的是,这在Android设备上似乎并不一致。也许有人可以评论如何最好地解决这个问题。