我可以确定用户点击了地球上的哪个位置。
当用户第一次单击鼠标按钮时,我可以存储他们单击的位置;让我们称之为pin
.
然后,当他们拖动鼠标时,我想将鼠标放在pin
鼠标光标下。
这是一些似乎大致保持pin
鼠标指针下方的代码,但没有正确保持地球;它随机闪烁和旋转。有时它会完全翻转轴,因此地球会暂时从后向前。
function evtPos(evt) {
if(!scene.ortho) return null;
var x = lerp(scene.ortho[0],scene.ortho[1],evt.clientX/canvas.width),
y = lerp(scene.ortho[3],scene.ortho[2],evt.clientY/canvas.height), // flipped
sqrd = x*x+y*y;
return (sqrd > 1)?
null:
mat4_vec3_multiply(mat4_inverse(scene.mvMatrix),[x,y,Math.sqrt(1-sqrd)]);
}
function onMouseDown(evt) {
pin = evtPos(evt);
}
function onMouseMove(evt,keys,isMouseDown) {
if(!isMouseDown) return;
var pt = evtPos(evt);
if(pin == null) pin = pt;
if(pt == null) return;
var d = vec3_sub(pt,pin),
rotx = Math.atan2(d[1],d[2]),
roty = (d[2] >= 0)?
-Math.atan2(d[0] * Math.cos(rotx),d[2]):
Math.atan2(d[0] * Math.cos(rotx),-d[2]),
rotz = Math.atan2(Math.cos(rotx),Math.sin(rotx)*Math.sin(roty));
scene.mvMatrix = mat4_multiply(scene.mvMatrix,mat4_rotation(rotx,[1,0,0]));
scene.mvMatrix = mat4_multiply(scene.mvMatrix,mat4_rotation(roty,[0,1,0]));
scene.mvMatrix = mat4_multiply(scene.mvMatrix,mat4_rotation(rotz,[0,0,1]));
}
function onMouseUp(evt) {
pin = null;
}
此外,随着时间的推移,似乎会出现错误,pin
并且距离鼠标指针越来越远。我想我应该以某种方式mvMatrix
完全计算每个事件而不是大量的小增量?
我希望用户能够拖动地球以自然地导航。我发现的所有旋转地球仪的代码都使用固定速度,例如箭头键,而不是在鼠标指针下“固定”地球仪。Unity 有一个Quaternion.FromToRotation(fromPos,toPos)
看起来很有前途的功能,但源代码不可用。