PerspectiveCamera.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. /**
  2. * @author mrdoob / http://mrdoob.com/
  3. * @author greggman / http://games.greggman.com/
  4. * @author zz85 / http://www.lab4games.net/zz85/blog
  5. * @author tschw
  6. */
  7. THREE.PerspectiveCamera = function( fov, aspect, near, far ) {
  8. THREE.Camera.call( this );
  9. this.type = 'PerspectiveCamera';
  10. this.fov = fov !== undefined ? fov : 50;
  11. this.zoom = 1;
  12. this.near = near !== undefined ? near : 0.1;
  13. this.far = far !== undefined ? far : 2000;
  14. this.focus = 10;
  15. this.aspect = aspect !== undefined ? aspect : 1;
  16. this.view = null;
  17. this.filmGauge = 35; // width of the film (default in millimeters)
  18. this.filmOffset = 0; // horizontal film offset (same unit as gauge)
  19. this.updateProjectionMatrix();
  20. };
  21. THREE.PerspectiveCamera.prototype = Object.assign( Object.create( THREE.Camera.prototype ), {
  22. constructor: THREE.PerspectiveCamera,
  23. copy: function ( source ) {
  24. THREE.Camera.prototype.copy.call( this, source );
  25. this.fov = source.fov;
  26. this.zoom = source.zoom;
  27. this.near = source.near;
  28. this.far = source.far;
  29. this.focus = source.focus;
  30. this.aspect = source.aspect;
  31. this.view = source.view === null ? null : Object.assign( {}, source.view );
  32. this.filmGauge = source.filmGauge;
  33. this.filmOffset = source.filmOffset;
  34. return this;
  35. },
  36. /**
  37. * Sets the FOV by focal length (DEPRECATED).
  38. *
  39. * Optionally also sets .filmGauge, otherwise uses it. See .setFocalLength.
  40. */
  41. setLens: function ( focalLength, filmGauge ) {
  42. console.warn( "THREE.PerspectiveCamera.setLens is deprecated. " +
  43. "Use .setFocalLength and .filmGauge for a photographic setup." );
  44. if ( filmGauge !== undefined ) this.filmGauge = filmGauge;
  45. this.setFocalLength( focalLength );
  46. },
  47. /**
  48. * Sets the FOV by focal length in respect to the current .filmGauge.
  49. *
  50. * The default film gauge is 35, so that the focal length can be specified for
  51. * a 35mm (full frame) camera.
  52. *
  53. * Values for focal length and film gauge must have the same unit.
  54. */
  55. setFocalLength: function ( focalLength ) {
  56. // see http://www.bobatkins.com/photography/technical/field_of_view.html
  57. var vExtentSlope = 0.5 * this.getFilmHeight() / focalLength;
  58. this.fov = THREE.Math.RAD2DEG * 2 * Math.atan( vExtentSlope );
  59. this.updateProjectionMatrix();
  60. },
  61. /**
  62. * Calculates the focal length from the current .fov and .filmGauge.
  63. */
  64. getFocalLength: function () {
  65. var vExtentSlope = Math.tan( THREE.Math.DEG2RAD * 0.5 * this.fov );
  66. return 0.5 * this.getFilmHeight() / vExtentSlope;
  67. },
  68. getEffectiveFOV: function () {
  69. return THREE.Math.RAD2DEG * 2 * Math.atan(
  70. Math.tan( THREE.Math.DEG2RAD * 0.5 * this.fov ) / this.zoom );
  71. },
  72. getFilmWidth: function () {
  73. // film not completely covered in portrait format (aspect < 1)
  74. return this.filmGauge * Math.min( this.aspect, 1 );
  75. },
  76. getFilmHeight: function () {
  77. // film not completely covered in landscape format (aspect > 1)
  78. return this.filmGauge / Math.max( this.aspect, 1 );
  79. },
  80. /**
  81. * Sets an offset in a larger frustum. This is useful for multi-window or
  82. * multi-monitor/multi-machine setups.
  83. *
  84. * For example, if you have 3x2 monitors and each monitor is 1920x1080 and
  85. * the monitors are in grid like this
  86. *
  87. * +---+---+---+
  88. * | A | B | C |
  89. * +---+---+---+
  90. * | D | E | F |
  91. * +---+---+---+
  92. *
  93. * then for each monitor you would call it like this
  94. *
  95. * var w = 1920;
  96. * var h = 1080;
  97. * var fullWidth = w * 3;
  98. * var fullHeight = h * 2;
  99. *
  100. * --A--
  101. * camera.setOffset( fullWidth, fullHeight, w * 0, h * 0, w, h );
  102. * --B--
  103. * camera.setOffset( fullWidth, fullHeight, w * 1, h * 0, w, h );
  104. * --C--
  105. * camera.setOffset( fullWidth, fullHeight, w * 2, h * 0, w, h );
  106. * --D--
  107. * camera.setOffset( fullWidth, fullHeight, w * 0, h * 1, w, h );
  108. * --E--
  109. * camera.setOffset( fullWidth, fullHeight, w * 1, h * 1, w, h );
  110. * --F--
  111. * camera.setOffset( fullWidth, fullHeight, w * 2, h * 1, w, h );
  112. *
  113. * Note there is no reason monitors have to be the same size or in a grid.
  114. */
  115. setViewOffset: function ( fullWidth, fullHeight, x, y, width, height ) {
  116. this.aspect = fullWidth / fullHeight;
  117. this.view = {
  118. fullWidth: fullWidth,
  119. fullHeight: fullHeight,
  120. offsetX: x,
  121. offsetY: y,
  122. width: width,
  123. height: height
  124. };
  125. this.updateProjectionMatrix();
  126. },
  127. updateProjectionMatrix: function () {
  128. var near = this.near,
  129. top = near * Math.tan(
  130. THREE.Math.DEG2RAD * 0.5 * this.fov ) / this.zoom,
  131. height = 2 * top,
  132. width = this.aspect * height,
  133. left = - 0.5 * width,
  134. view = this.view;
  135. if ( view !== null ) {
  136. var fullWidth = view.fullWidth,
  137. fullHeight = view.fullHeight;
  138. left += view.offsetX * width / fullWidth;
  139. top -= view.offsetY * height / fullHeight;
  140. width *= view.width / fullWidth;
  141. height *= view.height / fullHeight;
  142. }
  143. var skew = this.filmOffset;
  144. if ( skew !== 0 ) left += near * skew / this.getFilmWidth();
  145. this.projectionMatrix.makeFrustum(
  146. left, left + width, top - height, top, near, this.far );
  147. },
  148. toJSON: function ( meta ) {
  149. var data = THREE.Object3D.prototype.toJSON.call( this, meta );
  150. data.object.fov = this.fov;
  151. data.object.zoom = this.zoom;
  152. data.object.near = this.near;
  153. data.object.far = this.far;
  154. data.object.focus = this.focus;
  155. data.object.aspect = this.aspect;
  156. if ( this.view !== null ) data.object.view = Object.assign( {}, this.view );
  157. data.object.filmGauge = this.filmGauge;
  158. data.object.filmOffset = this.filmOffset;
  159. return data;
  160. }
  161. } );
粤ICP备19079148号