Raycaster.tests.js 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. /* global QUnit */
  2. import { Raycaster } from '../../../../src/core/Raycaster.js';
  3. import { Vector3 } from '../../../../src/math/Vector3.js';
  4. import { Mesh } from '../../../../src/objects/Mesh.js';
  5. import { SphereGeometry } from '../../../../src/geometries/SphereGeometry.js';
  6. import { BufferGeometry } from '../../../../src/core/BufferGeometry.js';
  7. import { Line } from '../../../../src/objects/Line.js';
  8. import { Points } from '../../../../src/objects/Points.js';
  9. import { PerspectiveCamera } from '../../../../src/cameras/PerspectiveCamera.js';
  10. import { OrthographicCamera } from '../../../../src/cameras/OrthographicCamera.js';
  11. function checkRayDirectionAgainstReferenceVector( rayDirection, refVector, assert ) {
  12. assert.ok( refVector.x - rayDirection.x <= Number.EPSILON && refVector.y - rayDirection.y <= Number.EPSILON && refVector.z - rayDirection.z <= Number.EPSILON, 'camera is pointing to' +
  13. ' the same direction as expected' );
  14. }
  15. function getRaycaster() {
  16. return new Raycaster(
  17. new Vector3( 0, 0, 0 ),
  18. new Vector3( 0, 0, - 1 ),
  19. 1,
  20. 100
  21. );
  22. }
  23. function getObjectsToCheck() {
  24. const objects = [];
  25. const sphere1 = getSphere();
  26. sphere1.position.set( 0, 0, - 10 );
  27. sphere1.name = 1;
  28. objects.push( sphere1 );
  29. const sphere11 = getSphere();
  30. sphere11.position.set( 0, 0, 1 );
  31. sphere11.name = 11;
  32. sphere1.add( sphere11 );
  33. const sphere12 = getSphere();
  34. sphere12.position.set( 0, 0, - 1 );
  35. sphere12.name = 12;
  36. sphere1.add( sphere12 );
  37. const sphere2 = getSphere();
  38. sphere2.position.set( - 5, 0, - 5 );
  39. sphere2.name = 2;
  40. objects.push( sphere2 );
  41. for ( let i = 0; i < objects.length; i ++ ) {
  42. objects[ i ].updateMatrixWorld();
  43. }
  44. return objects;
  45. }
  46. function getSphere() {
  47. return new Mesh( new SphereGeometry( 1, 100, 100 ) );
  48. }
  49. export default QUnit.module( 'Core', () => {
  50. QUnit.module( 'Raycaster', () => {
  51. // INSTANCING
  52. QUnit.test( 'Instancing', ( assert ) => {
  53. // no params
  54. const object = new Raycaster();
  55. assert.ok( object, 'Can instantiate a Raycaster.' );
  56. } );
  57. // PROPERTIES
  58. QUnit.todo( 'ray', ( assert ) => {
  59. assert.ok( false, 'everything\'s gonna be alright' );
  60. } );
  61. QUnit.todo( 'near', ( assert ) => {
  62. assert.ok( false, 'everything\'s gonna be alright' );
  63. } );
  64. QUnit.todo( 'far', ( assert ) => {
  65. assert.ok( false, 'everything\'s gonna be alright' );
  66. } );
  67. QUnit.todo( 'camera', ( assert ) => {
  68. assert.ok( false, 'everything\'s gonna be alright' );
  69. } );
  70. QUnit.todo( 'layers', ( assert ) => {
  71. assert.ok( false, 'everything\'s gonna be alright' );
  72. } );
  73. QUnit.todo( 'params', ( assert ) => {
  74. assert.ok( false, 'everything\'s gonna be alright' );
  75. } );
  76. // PUBLIC
  77. QUnit.test( 'set', ( assert ) => {
  78. const origin = new Vector3( 0, 0, 0 );
  79. const direction = new Vector3( 0, 0, - 1 );
  80. const a = new Raycaster( origin.clone(), direction.clone() );
  81. assert.deepEqual( a.ray.origin, origin, 'Origin is correct' );
  82. assert.deepEqual( a.ray.direction, direction, 'Direction is correct' );
  83. origin.set( 1, 1, 1 );
  84. direction.set( - 1, 0, 0 );
  85. a.set( origin, direction );
  86. assert.deepEqual( a.ray.origin, origin, 'Origin was set correctly' );
  87. assert.deepEqual( a.ray.direction, direction, 'Direction was set correctly' );
  88. } );
  89. QUnit.test( 'setFromCamera (Perspective)', ( assert ) => {
  90. const raycaster = new Raycaster();
  91. const rayDirection = raycaster.ray.direction;
  92. const camera = new PerspectiveCamera( 90, 1, 1, 1000 );
  93. raycaster.setFromCamera( {
  94. x: 0,
  95. y: 0
  96. }, camera );
  97. assert.ok( rayDirection.x === 0 && rayDirection.y === 0 && rayDirection.z === - 1,
  98. 'camera is looking straight to -z and so does the ray in the middle of the screen' );
  99. const step = 0.1;
  100. for ( let x = - 1; x <= 1; x += step ) {
  101. for ( let y = - 1; y <= 1; y += step ) {
  102. raycaster.setFromCamera( {
  103. x,
  104. y
  105. }, camera );
  106. const refVector = new Vector3( x, y, - 1 ).normalize();
  107. checkRayDirectionAgainstReferenceVector( rayDirection, refVector, assert );
  108. }
  109. }
  110. } );
  111. QUnit.test( 'setFromCamera (Orthographic)', ( assert ) => {
  112. const raycaster = new Raycaster();
  113. const rayOrigin = raycaster.ray.origin;
  114. const rayDirection = raycaster.ray.direction;
  115. const camera = new OrthographicCamera( - 1, 1, 1, - 1, 0, 1000 );
  116. const expectedOrigin = new Vector3( 0, 0, 0 );
  117. const expectedDirection = new Vector3( 0, 0, - 1 );
  118. raycaster.setFromCamera( {
  119. x: 0,
  120. y: 0
  121. }, camera );
  122. assert.deepEqual( rayOrigin, expectedOrigin, 'Ray origin has the right coordinates' );
  123. assert.deepEqual( rayDirection, expectedDirection, 'Camera and Ray are pointing towards -z' );
  124. } );
  125. QUnit.test( 'intersectObject', ( assert ) => {
  126. const raycaster = getRaycaster();
  127. const objectsToCheck = getObjectsToCheck();
  128. assert.ok( raycaster.intersectObject( objectsToCheck[ 0 ], false ).length === 1,
  129. 'no recursive search should lead to one hit' );
  130. assert.ok( raycaster.intersectObject( objectsToCheck[ 0 ] ).length === 3,
  131. 'recursive search should lead to three hits' );
  132. const intersections = raycaster.intersectObject( objectsToCheck[ 0 ] );
  133. for ( let i = 0; i < intersections.length - 1; i ++ ) {
  134. assert.ok( intersections[ i ].distance <= intersections[ i + 1 ].distance, 'intersections are sorted' );
  135. }
  136. } );
  137. QUnit.test( 'intersectObjects', ( assert ) => {
  138. const raycaster = getRaycaster();
  139. const objectsToCheck = getObjectsToCheck();
  140. assert.ok( raycaster.intersectObjects( objectsToCheck, false ).length === 1,
  141. 'no recursive search should lead to one hit' );
  142. assert.ok( raycaster.intersectObjects( objectsToCheck ).length === 3,
  143. 'recursive search should lead to three hits' );
  144. const intersections = raycaster.intersectObjects( objectsToCheck );
  145. for ( let i = 0; i < intersections.length - 1; i ++ ) {
  146. assert.ok( intersections[ i ].distance <= intersections[ i + 1 ].distance, 'intersections are sorted' );
  147. }
  148. } );
  149. QUnit.test( 'Line intersection threshold', ( assert ) => {
  150. const raycaster = getRaycaster();
  151. const points = [ new Vector3( - 2, - 10, - 5 ), new Vector3( - 2, 10, - 5 ) ];
  152. const geometry = new BufferGeometry().setFromPoints( points );
  153. const line = new Line( geometry, null );
  154. raycaster.params.Line.threshold = 1.999;
  155. assert.ok( raycaster.intersectObject( line ).length === 0,
  156. 'no Line intersection with a not-large-enough threshold' );
  157. raycaster.params.Line.threshold = 2.001;
  158. assert.ok( raycaster.intersectObject( line ).length === 1,
  159. 'successful Line intersection with a large-enough threshold' );
  160. } );
  161. QUnit.test( 'Points intersection threshold', ( assert ) => {
  162. const raycaster = getRaycaster();
  163. const coordinates = [ new Vector3( - 2, 0, - 5 ) ];
  164. const geometry = new BufferGeometry().setFromPoints( coordinates );
  165. const points = new Points( geometry, null );
  166. raycaster.params.Points.threshold = 1.999;
  167. assert.ok( raycaster.intersectObject( points ).length === 0,
  168. 'no Points intersection with a not-large-enough threshold' );
  169. raycaster.params.Points.threshold = 2.001;
  170. assert.ok( raycaster.intersectObject( points ).length === 1,
  171. 'successful Points intersection with a large-enough threshold' );
  172. } );
  173. } );
  174. } );
粤ICP备19079148号