Threejs Vector3 Unrpoject Camera

时间:2015-07-02 20:21:57

标签: javascript three.js projection

我正在以三个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>

编辑:我能够通过在渲染调用后直接移动动画来解决问题。这使我几乎可以确定没有更新相机矩阵是一个问题。我知道如何更新相机投影矩阵。如何强制相机的矩阵世界更新?

1 个答案:

答案 0 :(得分:2)

在three.js中,渲染器为每个渲染循环调用camera.updateMatrixWorld()

如果您修改了相机positionrotationquaternion,则使用依赖camera.matrixWorld的方法,如果该方法未更新{ {1}}本身,您必须手动更新矩阵。

camera.matrixWorld

three.js r.71