three.js 中正交相机的不精确射线投射

3
我正在使用three.js库开发一个CAD绘图的2D浏览器,为了完成这个项目,我需要能够单击场景中的对象来执行一些操作。但是,使用正交相机时,three.js的射线拾取并不像我期望的那样精确。以下是代码和fiddle链接,它们可以准确地展示我的意思:https://jsfiddle.net/toriphes/a0o7td1u/
var camera, scene, renderer, square, raycaster;
init();
animate();

function init() {

  output = document.getElementById('output');

  raycaster = new THREE.Raycaster();
  // Renderer.
  renderer = new THREE.WebGLRenderer();
  //renderer.setPixelRatio(window.devicePixelRatio);
  renderer.setSize(window.innerWidth, window.innerHeight);
  // Add renderer to page
  document.body.appendChild(renderer.domElement);

  // Create camera.
  var aspect = window.innerWidth / window.innerHeight;
  var d = 20;
  camera = new THREE.OrthographicCamera(-window.innerWidth / 2, window.innerWidth / 2, window.innerHeight / 2, -window.innerHeight / 2, 1, 1000);
  camera.position.z = 10;
  camera.position.x = 25;
  camera.position.y = 25;
  camera.zoom = 10
  camera.updateProjectionMatrix()

  controls = new THREE.OrbitControls(camera, renderer.domElement);
  controls.enableRotate = false
  controls.target.x = camera.position.x;
  controls.target.y = camera.position.y;

  controls.update();


  // Create scene.
  scene = new THREE.Scene();

  var points = [
    new THREE.Vector2(10, 10),
    new THREE.Vector2(40, 10),
    new THREE.Vector2(40, 40),
    new THREE.Vector2(10, 40),
    new THREE.Vector2(10, 10)
  ]

  var shape = new THREE.Shape(points);

  var geometry = new THREE.Geometry().setFromPoints(points);

  var square = new THREE.Line(geometry, new THREE.LineBasicMaterial({
    color: 0xFF0000
  }));
  scene.add(square)

  document.addEventListener('mousemove', findIntersections, false);
}

function animate() {
  requestAnimationFrame(animate);
  renderer.render(scene, camera);
}

function updateMousePosition(event) {
  return new THREE.Vector3(
    (event.clientX - renderer.domElement.offsetLeft) /
    renderer.domElement.clientWidth *
    2 -
    1,
    -(
      (event.clientY - renderer.domElement.offsetTop) /
      renderer.domElement.clientHeight
    ) *
    2 +
    1,
    0
  );
}

function findIntersections(e) {
  var mouseposition = updateMousePosition(e);
  raycaster.setFromCamera(mouseposition, camera);
  const intersects = raycaster.intersectObjects(scene.children);
  output.innerHTML = intersects.length > 0 ?
    'Intersect: TRUE' :
    'Intersect: FALSE';
}

如果你把鼠标靠近红色方块,你会发现交叉点触发在悬停边缘之前。

我做错了什么?

1个回答

3

线的相交检测取决于 .linePrecision 属性,该属性属于 Raycaster

例如:

raycaster.linePrecision = 0.1;
const intersects = raycaster.intersectObjects(scene.children);

参数必须根据场景的规模进行设置。0.1的值是一种经验值,对于您的示例可以得到很好的结果。遗憾的是文档中没有提供更多信息(也许我忽略了什么,但我没有找到)。


2
linePrecision = 0.1 在我的项目中似乎有效。更多关于它的文档说明会很有用。 - Giulio Ganci
很好的提示。我使用值0.01,这给了我想要的精度。但是假设这意味着当使用值0.1时,raycaster必须进行10x10=100倍的工作量。确实,linePrecision属性在官方文档中没有提到。但是在其中提到了params对象,其中threshold是射线投射与各种对象相交时的精度,以世界单位为单位。这解释了为什么有时很难选择网格对象,当线对象具有默认阈值1时。 - steveOw

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接