3d 调整相机以匹配光线和屏幕点
我正在使用three.js制作360度全景的免费查看工具。我希望当用户拖动屏幕上的点时,相机旋转,使该点正好位于鼠标指针下方3d 调整相机以匹配光线和屏幕点,3d,camera,three.js,3d,Camera,Three.js,我正在使用three.js制作360度全景的免费查看工具。我希望当用户拖动屏幕上的点时,相机旋转,使该点正好位于鼠标指针下方 几何体是围绕世界原点的简单长方体几何体,摄影机是位于原点的透视摄影机: this.mesh = new THREE.Mesh(new THREE.BoxGeometry(2, 2, 2, 0, 0, 0), new THREE.MeshFaceMaterial(_array_of_THREE.MeshBasicMaterial_)); this.camera =
几何体是围绕世界原点的简单长方体几何体,摄影机是位于原点的透视摄影机:
this.mesh = new THREE.Mesh(new THREE.BoxGeometry(2, 2, 2, 0, 0, 0),
new THREE.MeshFaceMaterial(_array_of_THREE.MeshBasicMaterial_));
this.camera = new THREE.PerspectiveCamera(90, width / height, 0.1, 2);
我有一个不准确的解决方案,它基于以下步骤:
adjustCamera: function(cameraDirection, worldRay, screenPoint){
var angle;
this.camera.lookAt(cameraDirection);
this.raycaster.setFromCamera(screenPoint, this.camera);
this.axis.copy(this.raycaster.ray.direction);
angle = this.axis.angleTo(worldRay);
this.axis.cross(worldRay).normalize();
this.ray.copy(cameraDirection);
this.ray.applyAxisAngle(this.axis, angle).normalize();
this.camera.lookAt(this.ray);
}
我明白了为什么这个模式不起作用。以这种方式更改的相机方向会产生一些滚动(当旋转轴的坐标不为零时),这一点通过查看消除-它会消除滚动,只留下俯仰和偏航。这会导致一些不精确性,当初始光线和最终光线距离较远时,以及当初始相机位置具有较高的俯仰时,误差会增大。我现在被困在这里,不知道如何在没有滚动的情况下计算摄像机的位置
因此,问题是:如何准确地旋转相机以将特定光线带到特定的屏幕点?(更适合我使用的模式)
编辑: 实际上,可以有多个(如果光线不指向最低点或天顶,似乎不超过两个)正确(无滚动)的相机位置将世界光线投影到屏幕上的特定点 想象一下下面的例子:接近天顶的光线应该和屏幕上半部分的点相匹配。第一个摄像头选项很明显,在这种情况下,第二个摄像头绕垂直轴旋转180度,并且具有更高的俯仰角。在第一个选项中,天顶投影在锁定点上方的屏幕上,在第二个选项中,天顶显示在下面
在这种模棱两可的情况下,应选择最接近初始相机方向的选项。无论何时处理旋转,最好使用该选项 我想说这个答案并不完整,因为它不会阻止相机滚动,但它会让你的起点在光标下,无论旋转如何。希望它能帮助我们找到一个完整的解决方案!代码可能也更有效,这是一个相当长的黑客会话 注意:您可以忽略着色器材质,这只是在测试时给我一个参考点
var canvas=document.getElementById('canvas');
var scene=new THREE.scene();
var renderer=new THREE.WebGLRenderer({canvas:canvas,antialas:true});
var摄像机=新的三视角摄像机(70,canvas.clientWidth/canvas.clientWidth,11000);
var geometry=新的3.BoxGeometry(10,10,10);
//var几何=新的三种。球墨法(500,50,50);
var material=新的3.ShaderMaterial({
vertexShader:document.getElementById('vertex-shader').textContent,
fragmentShader:document.getElementById('fragment-shader').textContent,
侧面:三。背面
});
var mesh=新的三个网格(几何体、材质);
场景。添加(网格);
render();
函数render(){
请求动画帧(渲染);
if(canvas.width!==canvas.clientWidth | | canvas.height!==canvas.clientHeight){
renderer.setSize(canvas.clientWidth、canvas.clientHeight、false);
camera.aspect=canvas.clientWidth/canvas.clientHeight;
camera.updateProjectMatrix();
}
渲染器。渲染(场景、摄影机);
}
//控制
var mousedown=false;
var raycaster=new THREE.raycaster();
var mouse=new THREE.Vector2();
var lastQuat=新的三个四元数();
var lastMouse=new THREE.Vector3();
var v=新的3.Vector3();
var-cam=camera.clone();
功能鼠标指针(v、x、y){
v、 设置(x/canvas.clientWidth*2-1,-y/canvas.clientHeight*2+1);
}
canvas.addEventListener('mousedown',函数(事件){
mousedown=true;
mouseToNDC(鼠标,event.layerX,event.layerY);
raycaster.setFromCamera(鼠标、相机);
复制(raycaster.ray.direction);
lastQuat.copy(相机四元数);
摄像机复制(摄像机);
});
window.addEventListener('mouseup',function(){
mousedown=false;
});
canvas.addEventListener('mousemove',函数(事件){
如果(鼠标向下){
mouseToNDC(鼠标,event.layerX,event.layerY);
raycaster.setFromCamera(鼠标、摄像头);
camera.quaternion.setFromUnitVectors(raycaster.ray.direction,lastMouse).multiply(lastQuat);
}
});代码>
html,主体,#画布{
保证金:0;
填充:0;
宽度:100%;
身高:100%;
溢出:隐藏;
}
可变vec2 vUv;
void main(){
vUv=紫外线;
gl_位置=projectionMatrix*modelViewMatrix*vec4(位置,1.0);
}
#定义毛头6.2831853071795864769252867665590
可变vec2 vUv;
void main(){
浮球x=地板(sin(5.0*M_头*vUv.x)/2.0+1.0);
浮动y=地板(sin(5.0*M_头*vUv.y)/2.0+1.0);
浮动c=最小值(x,y);
gl_FragColor=vec4(vec3(c),1.0);
}
为类似的全景图目的解决这个问题花费了相当长的时间
这里的复杂之处在于如何从摄像机注视方向
和固定滚动方向的向上
矢量构建旋转矩阵。矩阵最终投影常规X、Y和Z轴,以便:
- Z匹配注视
方向
- X垂直于Z和
向上矢量
- Y垂直于X和Z以使轴正交
像这样:
axisZ = direction;
axisX = normalize(cross(up, direction));
axisY = cross(direction, axisX);
由于向上
和方向
不垂直,我们需要对