XRPlanes.js 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. import {
  2. BoxGeometry,
  3. Matrix4,
  4. Mesh,
  5. MeshBasicMaterial,
  6. Object3D
  7. } from 'three';
  8. /**
  9. * A utility class for the WebXR Plane Detection Module. If planes
  10. * are detected by WebXR, this class will automatically add them
  11. * as thin box meshes to the scene when below code snippet is used.
  12. *
  13. * ```js
  14. * const planes = new XRPlanes( renderer );
  15. * scene.add( planes );
  16. * ```
  17. *
  18. * @augments Object3D
  19. */
  20. class XRPlanes extends Object3D {
  21. /**
  22. * Constructs a new XR plane container.
  23. *
  24. * @param {WebGLRenderer|WebGPURenderer} renderer - The renderer.
  25. */
  26. constructor( renderer ) {
  27. super();
  28. const matrix = new Matrix4();
  29. const currentPlanes = new Map();
  30. const xr = renderer.xr;
  31. xr.addEventListener( 'planesdetected', event => {
  32. const frame = event.data;
  33. const planes = frame.detectedPlanes;
  34. const referenceSpace = xr.getReferenceSpace();
  35. let planeschanged = false;
  36. for ( const [ plane, mesh ] of currentPlanes ) {
  37. if ( planes.has( plane ) === false ) {
  38. mesh.geometry.dispose();
  39. mesh.material.dispose();
  40. this.remove( mesh );
  41. currentPlanes.delete( plane );
  42. planeschanged = true;
  43. }
  44. }
  45. for ( const plane of planes ) {
  46. if ( currentPlanes.has( plane ) === false ) {
  47. const pose = frame.getPose( plane.planeSpace, referenceSpace );
  48. matrix.fromArray( pose.transform.matrix );
  49. const polygon = plane.polygon;
  50. let minX = Number.MAX_SAFE_INTEGER;
  51. let maxX = Number.MIN_SAFE_INTEGER;
  52. let minZ = Number.MAX_SAFE_INTEGER;
  53. let maxZ = Number.MIN_SAFE_INTEGER;
  54. for ( const point of polygon ) {
  55. minX = Math.min( minX, point.x );
  56. maxX = Math.max( maxX, point.x );
  57. minZ = Math.min( minZ, point.z );
  58. maxZ = Math.max( maxZ, point.z );
  59. }
  60. const width = maxX - minX;
  61. const height = maxZ - minZ;
  62. const geometry = new BoxGeometry( width, 0.01, height );
  63. const material = new MeshBasicMaterial( { color: 0xffffff * Math.random() } );
  64. const mesh = new Mesh( geometry, material );
  65. mesh.position.setFromMatrixPosition( matrix );
  66. mesh.quaternion.setFromRotationMatrix( matrix );
  67. this.add( mesh );
  68. currentPlanes.set( plane, mesh );
  69. planeschanged = true;
  70. }
  71. }
  72. if ( planeschanged ) {
  73. this.dispatchEvent( { type: 'planeschanged' } );
  74. }
  75. } );
  76. }
  77. }
  78. export { XRPlanes };
粤ICP备19079148号