ArrayCamera.js 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. /**
  2. * @author mrdoob / http://mrdoob.com/
  3. */
  4. import { PerspectiveCamera } from './PerspectiveCamera.js';
  5. import { Vector3 } from '../math/Vector3.js';
  6. function ArrayCamera( array ) {
  7. PerspectiveCamera.call( this );
  8. this.cameras = array || [];
  9. }
  10. ArrayCamera.prototype = Object.assign( Object.create( PerspectiveCamera.prototype ), {
  11. constructor: ArrayCamera,
  12. isArrayCamera: true,
  13. /**
  14. * Assumes 2 cameras that are perpendicular and share an X-axis, and that
  15. * the cameras' projection and world matrices have already been set.
  16. * And that near and far planes are identical for both cameras.
  17. */
  18. setProjectionFromUnion: function () {
  19. var cameraLPos = new Vector3();
  20. var cameraRPos = new Vector3();
  21. return function () {
  22. cameraLPos.setFromMatrixPosition( this.cameras[ 0 ].matrixWorld );
  23. cameraRPos.setFromMatrixPosition( this.cameras[ 1 ].matrixWorld );
  24. var ipd = cameraLPos.distanceTo( cameraRPos );
  25. var projL = this.cameras[ 0 ].projectionMatrix;
  26. var projR = this.cameras[ 1 ].projectionMatrix;
  27. // VR systems will have identical far and near planes, and
  28. // most likely identical top and bottom frustum extents.
  29. // via: https://computergraphics.stackexchange.com/a/4765
  30. var near = projL[ 14 ] / ( projL[ 10 ] - 1 );
  31. var far = projL[ 14 ] / ( projL[ 10 ] + 1 );
  32. var leftFovL = ( projL[ 8 ] - 1 ) / projL[ 0 ];
  33. var rightFovR = ( projR[ 8 ] + 1 ) / projR[ 0 ];
  34. var leftL = leftFovL * near;
  35. var rightR = rightFovR * near;
  36. var topL = near * ( projL[ 9 ] + 1 ) / projL[ 5 ];
  37. var topR = near * ( projR[ 9 ] + 1 ) / projR[ 5 ];
  38. var bottomL = near * ( projL[ 9 ] - 1 ) / projL[ 5 ];
  39. var bottomR = near * ( projR[ 9 ] - 1 ) / projR[ 5 ];
  40. // Calculate the new camera's position offset from the
  41. // left camera.
  42. var zOffset = ipd / (leftFovL + rightFovR);
  43. var xOffset = zOffset * leftFovL;
  44. // TODO: Better way to apply this offset?
  45. this.cameras[ 0 ].matrixWorld.decompose( this.position, this.quaternion, this.scale );
  46. this.translateX(xOffset);
  47. this.translateZ(-zOffset);
  48. this.matrixWorld.compose( this.position, this.quaternion, this.scale );
  49. this.matrixWorldInverse.getInverse(this.matrixWorld);
  50. // Find the union of the frustum values of the cameras and scale
  51. // the values so that the near plane's position does not change in world space,
  52. // although must now be relative to the new union camera.
  53. var near2 = near + zOffset;
  54. var far2 = far + zOffset;
  55. var left = leftL - xOffset;
  56. var right = rightR + (ipd - xOffset)
  57. var top = Math.max( topL, topR );
  58. var bottom = Math.min( bottomL, bottomR );
  59. this.projectionMatrix.makePerspective( left, right, top, bottom, near2, far2 );
  60. }
  61. }(),
  62. } );
  63. export { ArrayCamera };