ThreeJS 光线投射问题与等轴测视图中的正交相机

ThreeJS raycasting problem with an Orthographic camera in isometric-like view

我正在努力摆脱这个。我必须使用特定的摄像机角度来处理 3D 项目,并受到使用正交摄像机的限制。为了玩游戏,我需要能够精确地点击地板。 ThreeJS Raycast 似乎无法正常工作(或者我设置的方式有误?)。在像角度这样的自上而下的视图中,它效果更好。

这里有一个 fiddle 解释了我所处的情况:https://jsfiddle.net/p6td5oak/42/

const sceneWidth = window.innerWidth;
const sceneHeight = window.innerHeight;
const scene = new THREE.Scene();
const camera = new THREE.OrthographicCamera( -sceneWidth / 2, sceneWidth / 2, sceneHeight / 2, -sceneHeight / 2, -1000, 1000 );

camera.rotation.set(
    -Math.PI / 12,
  Math.PI / 12,
  Math.PI / 24
);
camera.position.set(0, 1, 0);
camera.zoom = 2;
camera.updateProjectionMatrix();

const renderer = new THREE.WebGLRenderer();
renderer.setSize( sceneWidth, sceneHeight );
document.body.appendChild( renderer.domElement );


const whiteMaterial = new THREE.MeshBasicMaterial({});

const redMaterial = new THREE.MeshBasicMaterial({
  color: 0xFF0000
});

const size = 100;
const geometry = new THREE.PlaneGeometry(size, size, 10, 10);

for (var x = 0; x < 2; x++)
{
        for (var z = 0; z < 2; z++)
    {
                let mesh = new THREE.Mesh(geometry, ((x + z) % 2 ? whiteMaterial : redMaterial));
        
        mesh.rotation.set(
            -Math.PI / 2,
          0,
          0
        );
        mesh.position.set(
            x*size,
          0,
          z*size
        )
        scene.add(mesh);
    }
}


var raycaster = new THREE.Raycaster();
window.addEventListener("pointerup", function(e)
{
    var screenPos = new THREE.Vector2();
  
  screenPos.x = (e.clientX / window.innerWidth) * 2 - 1;
  screenPos.y = - (e.clientY / window.innerHeight) * 2 + 1;
  
    raycaster.setFromCamera(screenPos, camera);
  
  var rays = raycaster.intersectObjects(scene.children, true);
  
    for (var i = 0; i < rays.length; i++)
  {
    scene.remove(rays[i].object);
  }
}
.bind(this));




function animate() {
    requestAnimationFrame( animate );
    renderer.render( scene, camera );
}
animate();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>

在示例中,我尝试在单击平面后立即将其删除。如您所见,如果单击它们的左上角,可以删除顶部的两个平面。另外两个连触发都触发不了

如果有人知道发生了什么,你就是我的英雄。

谢谢!

PS:我对 ThreeJS 有基本的了解,但还远不是专家

Raycaster 仅检测相机前方的物体,并且您的相机位于原点附近。将相机移回。

此外,您的正交相机的 near 值无效。来自 documentation:

The valid range is between 0 and the current value of the far plane.

不支持负值。

const sceneWidth = window.innerWidth;
const sceneHeight = window.innerHeight;
const scene = new THREE.Scene();
const camera = new THREE.OrthographicCamera(-sceneWidth / 2, sceneWidth / 2, sceneHeight / 2, -sceneHeight / 2, 0.1, 1000);

camera.rotation.set(
  -Math.PI / 12,
  Math.PI / 12,
  Math.PI / 24
);
camera.position.set(100, 100, 500);
camera.zoom = 2;
camera.updateProjectionMatrix();

const renderer = new THREE.WebGLRenderer({
  antialias: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(sceneWidth, sceneHeight);
document.body.appendChild(renderer.domElement);

const whiteMaterial = new THREE.MeshBasicMaterial();

const redMaterial = new THREE.MeshBasicMaterial({
  color: 0xFF0000
});

const size = 100;
const geometry = new THREE.PlaneGeometry(size, size, 10, 10);

for (let x = 0; x < 2; x++) {
  for (let z = 0; z < 2; z++) {
    let mesh = new THREE.Mesh(geometry, ((x + z) % 2 ? whiteMaterial : redMaterial));

    mesh.rotation.set(
      -Math.PI / 2,
      0,
      0
    );
    mesh.position.set(
      x * size,
      0,
      z * size
    )
    scene.add(mesh);
  }
}


const raycaster = new THREE.Raycaster();
const screenPos = new THREE.Vector2();

renderer.domElement.addEventListener("pointerup", function(e) {

  screenPos.x = (e.clientX / window.innerWidth) * 2 - 1;
  screenPos.y = -(e.clientY / window.innerHeight) * 2 + 1;

  raycaster.setFromCamera(screenPos, camera);

  const intersections = raycaster.intersectObject(scene, true);

  for (let i = 0; i < intersections.length; i++) {
    scene.remove(intersections[i].object);
  }
});

function animate() {
  requestAnimationFrame(animate);
  renderer.render(scene, camera);
}
animate();
body {
    margin: 0;
}
<script src="https://cdn.jsdelivr.net/npm/three@0.129/build/three.js"></script>