我正在以三个j开展一个项目。我正在尝试将2D坐标投影到世界上的球体上。
当我将函数绑定到mousedown事件时,下面的代码非常有效:
function project(point){
var x = 2 * (point[0] - width/2) / width;
var y = 2 * (point[1] - height/2) / height;
var l = new THREE.Vector3(x, y, 0.5);
l.unproject(camera);
l.sub(camera.position).normalize(); // ray / direction of click on world coordinates
// Below is code for Ray Sphere Intersection (I'm certain this works)
var omc = camera.position.clone().sub(sphere.position);
var ldomc = l.dot(omc);
var d = -ldomc - Math.sqrt(ldomc*ldomc - omc.lengthSq() + radius*radius);
if (d == d){ // if there was an intersection
return camera.position.clone().add(l.multiplyScalar(d));
}
return null; // If no intersection was found
}
但是,当我尝试在下面的代码中使用上面的函数时,函数只返回null(没有找到交集)。
get_random_point(scale){ // scale is the projected radius (in pixels) of the sphere
while (true){ // continue until a point works
var a = Math.random();
var b = Math.sqrt(Math.random());
var x = width/2 + scale * b * Math.cos(2 * Math.PI * a);
var y = height/2 + scale * b * Math.sin(2 * Math.PI * a);
if (width > x && x >= 0 && height > y && y >= 0){
var projp = project([x,y]);
if (projp != null){
return toSpherical(projp); // Return spherical coordinates of point
}
}
}
}
上面的代码被称为每个动画周期约100次,以选择球体表面上相机可见的随机点。
只有在移动相机后才会出现此问题。 我使用鼠标控制相机使其围绕球体运行。
当发生这种情况时,我设法将项目中声明的所有变量转储到javascript控制台。然后,我在具有相同相机姿势和点的不同选项卡中测试了项目功能,发现计算出的光线不正确。
以下是相机控制的功能:
d3.select("body").on("mousedown", function(event){
m0 = d3.mouse(this);
});
d3.select("body").on("mousemove", function(event){
if (m0 != null){
var m1 = d3.mouse(this);
var mv = [m1[0] - m0[0], m1[1] - m0[1]];
theta -= mv[0]*0.25/180.0*Math.PI;
phi += mv[1]*0.25/180.0*Math.PI*camera.up.y;
if (phi > Math.PI/2){ phi = Math.PI - phi; camera.up.y *= -1; theta += Math.PI}
if (-Math.PI/2 > phi){ phi = -Math.PI -phi; camera.up.y *= -1; theta += Math.PI}
while (theta >= 2 * Math.PI){ theta -= 2 * Math.PI; }
while ( 0 > theta){ theta += 2 * Math.PI; }
camera.position.x = r * Math.sin(theta) * Math.cos(phi);
camera.position.y = r * Math.sin(phi);
camera.position.z = r * Math.cos(theta) * Math.cos(phi);
camera.lookAt(new THREE.Vector3(0, 0, 0));
m0 = m1;
}
});
d3.select("body").on("mouseup", function(event){
m0 = null;
}).on("mouseleave", function(event){ m0 = null; });
function Zoom(event){
var movement;
if (event.wheelDelta){
movement = event.wheelDelta/120; // wheelDelta is in increments of 120
} else {
movement = event.deltaY/-3; // DeltaY is in increments of 3;
}
r -= 0.05 * movement;
if (0.9 > r){
r = 0.9;
} else if (r > 2.5){
r = 2.5;
}
camera.position.x = r * Math.sin(theta) * Math.cos(phi);
camera.position.y = r * Math.sin(phi);
camera.position.z = r * Math.cos(theta) * Math.cos(phi);
camera.lookAt(new THREE.Vector3(0, 0, 0));
}
我似乎无法弄清楚为什么当没有从动画循环中调用时,项目功能可以用于同一点和相机姿势。
我的猜测是在鼠标移动回调期间修改了摄像机,但是其中一个摄像机的矩阵没有更新,导致Three.Vector3.unproject()函数无法提供所需的输出。 / p>
编辑:我能够通过在渲染调用后直接移动动画来解决问题。这使我几乎可以确定没有更新相机矩阵是一个问题。我知道如何更新相机投影矩阵。如何强制相机的矩阵世界更新?
答案 0 :(得分:2)
在three.js中,渲染器为每个渲染循环调用camera.updateMatrixWorld()
。
如果您修改了相机position
,rotation
或quaternion
,则使用依赖camera.matrixWorld
的方法,如果该方法未更新{ {1}}本身,您必须手动更新矩阵。
camera.matrixWorld
three.js r.71