CombinedCamera.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. /**
  2. * @author zz85 / http://twitter.com/blurspline / http://www.lab4games.net/zz85/blog
  3. *
  4. * A general perpose camera, for setting FOV, Lens Focal Length,
  5. * and switching between perspective and orthographic views easily.
  6. * Use this only if you do not wish to manage
  7. * both a Orthographic and Perspective Camera
  8. *
  9. */
  10. THREE.CombinedCamera = function ( width, height, fov, near, far, orthoNear, orthoFar ) {
  11. THREE.Camera.call( this );
  12. this.fov = fov;
  13. this.far = far;
  14. this.near = near;
  15. this.left = - width / 2;
  16. this.right = width / 2;
  17. this.top = height / 2;
  18. this.bottom = - height / 2;
  19. this.aspect = width / height;
  20. this.zoom = 1;
  21. this.view = null;
  22. // We could also handle the projectionMatrix internally, but just wanted to test nested camera objects
  23. this.cameraO = new THREE.OrthographicCamera( width / - 2, width / 2, height / 2, height / - 2, orthoNear, orthoFar );
  24. this.cameraP = new THREE.PerspectiveCamera( fov, width / height, near, far );
  25. this.toPerspective();
  26. };
  27. THREE.CombinedCamera.prototype = Object.create( THREE.Camera.prototype );
  28. THREE.CombinedCamera.prototype.constructor = THREE.CombinedCamera;
  29. THREE.CombinedCamera.prototype.toPerspective = function () {
  30. // Switches to the Perspective Camera
  31. this.near = this.cameraP.near;
  32. this.far = this.cameraP.far;
  33. this.cameraP.aspect = this.aspect;
  34. this.cameraP.fov = this.fov / this.zoom ;
  35. this.cameraP.view = this.view;
  36. this.cameraP.updateProjectionMatrix();
  37. this.projectionMatrix = this.cameraP.projectionMatrix;
  38. this.inPerspectiveMode = true;
  39. this.inOrthographicMode = false;
  40. };
  41. THREE.CombinedCamera.prototype.toOrthographic = function () {
  42. // Switches to the Orthographic camera estimating viewport from Perspective
  43. var fov = this.fov;
  44. var aspect = this.cameraP.aspect;
  45. var near = this.cameraP.near;
  46. var far = this.cameraP.far;
  47. // The size that we set is the mid plane of the viewing frustum
  48. var hyperfocus = ( near + far ) / 2;
  49. var halfHeight = Math.tan( fov * Math.PI / 180 / 2 ) * hyperfocus;
  50. var halfWidth = halfHeight * aspect;
  51. halfHeight /= this.zoom;
  52. halfWidth /= this.zoom;
  53. this.cameraO.left = - halfWidth;
  54. this.cameraO.right = halfWidth;
  55. this.cameraO.top = halfHeight;
  56. this.cameraO.bottom = - halfHeight;
  57. this.cameraO.view = this.view;
  58. this.cameraO.updateProjectionMatrix();
  59. this.near = this.cameraO.near;
  60. this.far = this.cameraO.far;
  61. this.projectionMatrix = this.cameraO.projectionMatrix;
  62. this.inPerspectiveMode = false;
  63. this.inOrthographicMode = true;
  64. };
  65. THREE.CombinedCamera.prototype.copy = function ( source ) {
  66. THREE.Camera.prototype.copy.call( this, source );
  67. this.fov = source.fov;
  68. this.far = source.far;
  69. this.near = source.near;
  70. this.left = source.left;
  71. this.right = source.right;
  72. this.top = source.top;
  73. this.bottom = source.bottom;
  74. this.zoom = source.zoom;
  75. this.view = source.view === null ? null : Object.assign( {}, source.view );
  76. this.aspect = source.aspect;
  77. this.cameraO.copy( source.cameraO );
  78. this.cameraP.copy( source.cameraP );
  79. this.inOrthographicMode = source.inOrthographicMode;
  80. this.inPerspectiveMode = source.inPerspectiveMode;
  81. return this;
  82. };
  83. THREE.CombinedCamera.prototype.setViewOffset = function( fullWidth, fullHeight, x, y, width, height ) {
  84. this.view = {
  85. fullWidth: fullWidth,
  86. fullHeight: fullHeight,
  87. offsetX: x,
  88. offsetY: y,
  89. width: width,
  90. height: height
  91. };
  92. if ( this.inPerspectiveMode ) {
  93. this.aspect = fullWidth / fullHeight;
  94. this.toPerspective();
  95. } else {
  96. this.toOrthographic();
  97. }
  98. };
  99. THREE.CombinedCamera.prototype.clearViewOffset = function() {
  100. this.view = null;
  101. this.updateProjectionMatrix();
  102. };
  103. THREE.CombinedCamera.prototype.setSize = function( width, height ) {
  104. this.cameraP.aspect = width / height;
  105. this.left = - width / 2;
  106. this.right = width / 2;
  107. this.top = height / 2;
  108. this.bottom = - height / 2;
  109. };
  110. THREE.CombinedCamera.prototype.setFov = function( fov ) {
  111. this.fov = fov;
  112. if ( this.inPerspectiveMode ) {
  113. this.toPerspective();
  114. } else {
  115. this.toOrthographic();
  116. }
  117. };
  118. // For maintaining similar API with PerspectiveCamera
  119. THREE.CombinedCamera.prototype.updateProjectionMatrix = function() {
  120. if ( this.inPerspectiveMode ) {
  121. this.toPerspective();
  122. } else {
  123. this.toPerspective();
  124. this.toOrthographic();
  125. }
  126. };
  127. /*
  128. * Uses Focal Length (in mm) to estimate and set FOV
  129. * 35mm (full frame) camera is used if frame size is not specified;
  130. * Formula based on http://www.bobatkins.com/photography/technical/field_of_view.html
  131. */
  132. THREE.CombinedCamera.prototype.setLens = function ( focalLength, filmGauge ) {
  133. if ( filmGauge === undefined ) filmGauge = 35;
  134. var vExtentSlope = 0.5 * filmGauge /
  135. ( focalLength * Math.max( this.cameraP.aspect, 1 ) );
  136. var fov = THREE.Math.RAD2DEG * 2 * Math.atan( vExtentSlope );
  137. this.setFov( fov );
  138. return fov;
  139. };
  140. THREE.CombinedCamera.prototype.setZoom = function( zoom ) {
  141. this.zoom = zoom;
  142. if ( this.inPerspectiveMode ) {
  143. this.toPerspective();
  144. } else {
  145. this.toOrthographic();
  146. }
  147. };
  148. THREE.CombinedCamera.prototype.toFrontView = function() {
  149. this.rotation.x = 0;
  150. this.rotation.y = 0;
  151. this.rotation.z = 0;
  152. // should we be modifing the matrix instead?
  153. };
  154. THREE.CombinedCamera.prototype.toBackView = function() {
  155. this.rotation.x = 0;
  156. this.rotation.y = Math.PI;
  157. this.rotation.z = 0;
  158. };
  159. THREE.CombinedCamera.prototype.toLeftView = function() {
  160. this.rotation.x = 0;
  161. this.rotation.y = - Math.PI / 2;
  162. this.rotation.z = 0;
  163. };
  164. THREE.CombinedCamera.prototype.toRightView = function() {
  165. this.rotation.x = 0;
  166. this.rotation.y = Math.PI / 2;
  167. this.rotation.z = 0;
  168. };
  169. THREE.CombinedCamera.prototype.toTopView = function() {
  170. this.rotation.x = - Math.PI / 2;
  171. this.rotation.y = 0;
  172. this.rotation.z = 0;
  173. };
  174. THREE.CombinedCamera.prototype.toBottomView = function() {
  175. this.rotation.x = Math.PI / 2;
  176. this.rotation.y = 0;
  177. this.rotation.z = 0;
  178. };