StereoCamera.js 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. import { Matrix4 } from '../math/Matrix4.js';
  2. import * as MathUtils from '../math/MathUtils.js';
  3. import { PerspectiveCamera } from './PerspectiveCamera.js';
  4. const _eyeRight = /*@__PURE__*/ new Matrix4();
  5. const _eyeLeft = /*@__PURE__*/ new Matrix4();
  6. class StereoCamera {
  7. constructor() {
  8. this.type = 'StereoCamera';
  9. this.aspect = 1;
  10. this.eyeSep = 0.064;
  11. this.cameraL = new PerspectiveCamera();
  12. this.cameraL.layers.enable( 1 );
  13. this.cameraL.matrixAutoUpdate = false;
  14. this.cameraR = new PerspectiveCamera();
  15. this.cameraR.layers.enable( 2 );
  16. this.cameraR.matrixAutoUpdate = false;
  17. this._cache = {
  18. focus: null,
  19. fov: null,
  20. aspect: null,
  21. near: null,
  22. far: null,
  23. zoom: null,
  24. eyeSep: null
  25. };
  26. }
  27. update( camera ) {
  28. const cache = this._cache;
  29. const needsUpdate = cache.focus !== camera.focus || cache.fov !== camera.fov ||
  30. cache.aspect !== camera.aspect * this.aspect || cache.near !== camera.near ||
  31. cache.far !== camera.far || cache.zoom !== camera.zoom || cache.eyeSep !== this.eyeSep;
  32. if ( needsUpdate ) {
  33. cache.focus = camera.focus;
  34. cache.fov = camera.fov;
  35. cache.aspect = camera.aspect * this.aspect;
  36. cache.near = camera.near;
  37. cache.far = camera.far;
  38. cache.zoom = camera.zoom;
  39. cache.eyeSep = this.eyeSep;
  40. // Off-axis stereoscopic effect based on
  41. // http://paulbourke.net/stereographics/stereorender/
  42. const projectionMatrix = camera.projectionMatrix.clone();
  43. const eyeSepHalf = cache.eyeSep / 2;
  44. const eyeSepOnProjection = eyeSepHalf * cache.near / cache.focus;
  45. const ymax = ( cache.near * Math.tan( MathUtils.DEG2RAD * cache.fov * 0.5 ) ) / cache.zoom;
  46. let xmin, xmax;
  47. // translate xOffset
  48. _eyeLeft.elements[ 12 ] = - eyeSepHalf;
  49. _eyeRight.elements[ 12 ] = eyeSepHalf;
  50. // for left eye
  51. xmin = - ymax * cache.aspect + eyeSepOnProjection;
  52. xmax = ymax * cache.aspect + eyeSepOnProjection;
  53. projectionMatrix.elements[ 0 ] = 2 * cache.near / ( xmax - xmin );
  54. projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
  55. this.cameraL.projectionMatrix.copy( projectionMatrix );
  56. // for right eye
  57. xmin = - ymax * cache.aspect - eyeSepOnProjection;
  58. xmax = ymax * cache.aspect - eyeSepOnProjection;
  59. projectionMatrix.elements[ 0 ] = 2 * cache.near / ( xmax - xmin );
  60. projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
  61. this.cameraR.projectionMatrix.copy( projectionMatrix );
  62. }
  63. this.cameraL.matrixWorld.copy( camera.matrixWorld ).multiply( _eyeLeft );
  64. this.cameraR.matrixWorld.copy( camera.matrixWorld ).multiply( _eyeRight );
  65. }
  66. }
  67. export { StereoCamera };
粤ICP备19079148号