Преглед на файлове

Raycaster: Fix `setFromCamera()` with ortho cameras. (#33568)

Michael Herzog преди 1 месец
родител
ревизия
93da37dc0e
променени са 2 файла, в които са добавени 119 реда и са изтрити 1 реда
  1. 18 1
      src/core/Raycaster.js
  2. 101 0
      test/unit/src/core/Raycaster.tests.js

+ 18 - 1
src/core/Raycaster.js

@@ -2,6 +2,7 @@ import { Matrix4 } from '../math/Matrix4.js';
 import { Ray } from '../math/Ray.js';
 import { Ray } from '../math/Ray.js';
 import { Layers } from './Layers.js';
 import { Layers } from './Layers.js';
 import { error } from '../utils.js';
 import { error } from '../utils.js';
+import { WebGPUCoordinateSystem } from '../constants.js';
 
 
 const _matrix = /*@__PURE__*/ new Matrix4();
 const _matrix = /*@__PURE__*/ new Matrix4();
 
 
@@ -126,7 +127,23 @@ class Raycaster {
 
 
 		} else if ( camera.isOrthographicCamera ) {
 		} else if ( camera.isOrthographicCamera ) {
 
 
-			this.ray.origin.set( coords.x, coords.y, ( camera.near + camera.far ) / ( camera.near - camera.far ) ).unproject( camera ); // set origin in plane of camera
+			let coordsZ;
+
+			if ( camera.reversedDepth ) {
+
+				coordsZ = camera.far / ( camera.far - camera.near );
+
+			} else if ( camera.coordinateSystem === WebGPUCoordinateSystem ) {
+
+				coordsZ = camera.near / ( camera.near - camera.far );
+
+			} else {
+
+				coordsZ = ( camera.near + camera.far ) / ( camera.near - camera.far );
+
+			}
+
+			this.ray.origin.set( coords.x, coords.y, coordsZ ).unproject( camera ); // set origin in plane of camera
 			this.ray.direction.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld );
 			this.ray.direction.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld );
 			this.camera = camera;
 			this.camera = camera;
 
 

+ 101 - 0
test/unit/src/core/Raycaster.tests.js

@@ -7,6 +7,7 @@ import { Line } from '../../../../src/objects/Line.js';
 import { Points } from '../../../../src/objects/Points.js';
 import { Points } from '../../../../src/objects/Points.js';
 import { PerspectiveCamera } from '../../../../src/cameras/PerspectiveCamera.js';
 import { PerspectiveCamera } from '../../../../src/cameras/PerspectiveCamera.js';
 import { OrthographicCamera } from '../../../../src/cameras/OrthographicCamera.js';
 import { OrthographicCamera } from '../../../../src/cameras/OrthographicCamera.js';
+import { WebGPUCoordinateSystem } from '../../../../src/constants.js';
 
 
 function checkRayDirectionAgainstReferenceVector( rayDirection, refVector, assert ) {
 function checkRayDirectionAgainstReferenceVector( rayDirection, refVector, assert ) {
 
 
@@ -190,6 +191,106 @@ export default QUnit.module( 'Core', () => {
 
 
 		} );
 		} );
 
 
+		QUnit.test( 'intersectObject (Perspective, WebGPU coordinate system)', ( assert ) => {
+
+			const camera = new PerspectiveCamera( 90, 1, 0.1, 100 );
+			camera.coordinateSystem = WebGPUCoordinateSystem;
+			camera.updateProjectionMatrix();
+
+			const front = getSphere();
+			front.position.set( 0, 0, - 5 );
+			front.updateMatrixWorld();
+
+			const behind = getSphere();
+			behind.position.set( 0, 0, 5 );
+			behind.updateMatrixWorld();
+
+			const raycaster = new Raycaster();
+			raycaster.setFromCamera( { x: 0, y: 0 }, camera );
+
+			assert.strictEqual( raycaster.intersectObject( front ).length, 1,
+				'Sphere in front of the perspective camera is intersected under WebGPU coordinate system.' );
+
+			assert.strictEqual( raycaster.intersectObject( behind ).length, 0,
+				'Sphere behind the perspective camera is not intersected under WebGPU coordinate system.' );
+
+		} );
+
+		QUnit.test( 'intersectObject (Orthographic, WebGPU coordinate system)', ( assert ) => {
+
+			const camera = new OrthographicCamera( - 1, 1, 1, - 1, 0.1, 10 );
+			camera.coordinateSystem = WebGPUCoordinateSystem;
+			camera.updateProjectionMatrix();
+
+			const front = getSphere();
+			front.position.set( 0, 0, - 5 );
+			front.updateMatrixWorld();
+
+			const behind = getSphere();
+			behind.position.set( 0, 0, 5 );
+			behind.updateMatrixWorld();
+
+			const raycaster = new Raycaster();
+			raycaster.setFromCamera( { x: 0, y: 0 }, camera );
+
+			assert.strictEqual( raycaster.intersectObject( front ).length, 1,
+				'Sphere in front of the orthographic camera is intersected under WebGPU coordinate system.' );
+
+			assert.strictEqual( raycaster.intersectObject( behind ).length, 0,
+				'Sphere behind the orthographic camera is not intersected under WebGPU coordinate system.' );
+
+		} );
+
+		QUnit.test( 'intersectObject (Perspective, reversed depth)', ( assert ) => {
+
+			const camera = new PerspectiveCamera( 90, 1, 0.1, 100 );
+			camera._reversedDepth = true;
+			camera.updateProjectionMatrix();
+
+			const front = getSphere();
+			front.position.set( 0, 0, - 5 );
+			front.updateMatrixWorld();
+
+			const behind = getSphere();
+			behind.position.set( 0, 0, 5 );
+			behind.updateMatrixWorld();
+
+			const raycaster = new Raycaster();
+			raycaster.setFromCamera( { x: 0, y: 0 }, camera );
+
+			assert.strictEqual( raycaster.intersectObject( front ).length, 1,
+				'Sphere in front of the perspective camera is intersected with reversed depth.' );
+
+			assert.strictEqual( raycaster.intersectObject( behind ).length, 0,
+				'Sphere behind the perspective camera is not intersected with reversed depth.' );
+
+		} );
+
+		QUnit.test( 'intersectObject (Orthographic, reversed depth)', ( assert ) => {
+
+			const camera = new OrthographicCamera( - 1, 1, 1, - 1, 0.1, 10 );
+			camera._reversedDepth = true;
+			camera.updateProjectionMatrix();
+
+			const front = getSphere();
+			front.position.set( 0, 0, - 5 );
+			front.updateMatrixWorld();
+
+			const behind = getSphere();
+			behind.position.set( 0, 0, 5 );
+			behind.updateMatrixWorld();
+
+			const raycaster = new Raycaster();
+			raycaster.setFromCamera( { x: 0, y: 0 }, camera );
+
+			assert.strictEqual( raycaster.intersectObject( front ).length, 1,
+				'Sphere in front of the orthographic camera is intersected with reversed depth.' );
+
+			assert.strictEqual( raycaster.intersectObject( behind ).length, 0,
+				'Sphere behind the orthographic camera is not intersected with reversed depth.' );
+
+		} );
+
 		QUnit.test( 'Line intersection threshold', ( assert ) => {
 		QUnit.test( 'Line intersection threshold', ( assert ) => {
 
 
 			const raycaster = getRaycaster();
 			const raycaster = getRaycaster();

粤ICP备19079148号