Camera.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. /**
  2. * @author mr.doob / http://mrdoob.com/
  3. * @author mikael emtinger / http://gomo.se/
  4. */
  5. THREE.Camera = function( FOV, aspect, zNear, zFar, renderer, target ) {
  6. THREE.Object3D.call( this );
  7. this.FOV = FOV || 50;
  8. this.aspect = aspect || 1.0;
  9. this.zNear = zNear || 0.1;
  10. this.zFar = zFar || 2000;
  11. this.screenCenterX = 0;
  12. this.screenCenterY = 0;
  13. this.target = target || new THREE.Object3D();
  14. this.useTarget = true;
  15. this.up = new THREE.Vector3( 0, 1, 0 );
  16. this.inverseMatrix = new THREE.Matrix4();
  17. this.projectionMatrix = null;
  18. // movement
  19. this.tmpVec = new THREE.Vector3();
  20. this.translateX = function ( amount ) {
  21. this.tmpVec.sub( this.target.position, this.position ).normalize().multiplyScalar( amount );
  22. this.tmpVec.crossSelf( this.up );
  23. this.position.addSelf( this.tmpVec );
  24. this.target.position.addSelf( this.tmpVec );
  25. };
  26. /* TODO
  27. this.translateY = function ( amount ) {
  28. };
  29. */
  30. this.translateZ = function ( amount ) {
  31. this.tmpVec.sub( this.target.position, this.position ).normalize().multiplyScalar( amount );
  32. this.position.subSelf( this.tmpVec );
  33. this.target.position.subSelf( this.tmpVec );
  34. };
  35. this.updateProjectionMatrix();
  36. }
  37. THREE.Camera.prototype = new THREE.Object3D();
  38. THREE.Camera.prototype.constructor = THREE.Camera;
  39. THREE.Camera.prototype.supr = THREE.Object3D.prototype;
  40. /*
  41. * Update projection matrix
  42. *
  43. * TODO: make it work also for ortho camera
  44. */
  45. THREE.Camera.prototype.updateProjectionMatrix = function() {
  46. this.projectionMatrix = THREE.Matrix4.makePerspective( this.FOV, this.aspect, this.zNear, this.zFar );
  47. }
  48. /*
  49. * Update
  50. */
  51. THREE.Camera.prototype.update = function( parentGlobalMatrix, forceUpdate, camera ) {
  52. if( this.useTarget ) {
  53. // local
  54. this.localMatrix.lookAt( this.position, this.target.position, this.up );
  55. // global
  56. if( parentGlobalMatrix )
  57. this.globalMatrix.multiply( parentGlobalMatrix, this.localMatrix );
  58. else
  59. this.globalMatrix.copy( this.localMatrix );
  60. THREE.Matrix4.makeInvert( this.globalMatrix, this.inverseMatrix );
  61. //THREE.Matrix4.makeInvertTo( this.globalMatrix, this.inverseMatrix );
  62. forceUpdate = true;
  63. } else {
  64. if( this.matrixAutoUpdate )
  65. forceUpdate |= this.updateMatrix();
  66. if( forceUpdate || this.matrixNeedsUpdate ) {
  67. if( parentGlobalMatrix )
  68. this.globalMatrix.multiply( parentGlobalMatrix, this.localMatrix );
  69. else
  70. this.globalMatrix.copy( this.localMatrix );
  71. this.matrixNeedsUpdate = false;
  72. forceUpdate = true;
  73. THREE.Matrix4.makeInvert( this.globalMatrix, this.inverseMatrix );
  74. //THREE.Matrix4.makeInvertTo( this.globalMatrix, this.inverseMatrix );
  75. }
  76. }
  77. // update children
  78. for( var i = 0; i < this.children.length; i++ )
  79. this.children[ i ].update( this.globalMatrix, forceUpdate, camera );
  80. };
  81. /*
  82. * FrustumContains
  83. * Checks object against projected image (as opposed to ordinary frustum check)
  84. *
  85. * TODO: make it work also for ortho camera
  86. */
  87. THREE.Camera.prototype.frustumContains = function( object3D ) {
  88. // object pos
  89. var vx0 = object3D.globalMatrix.n14,
  90. vy0 = object3D.globalMatrix.n24,
  91. vz0 = object3D.globalMatrix.n34;
  92. // check z
  93. var inverse = this.inverseMatrix;
  94. var radius = object3D.boundRadius * object3D.boundRadiusScale;
  95. var vz1 = ( inverse.n31 * vx0 + inverse.n32 * vy0 + inverse.n33 * vz0 + inverse.n34 );
  96. if( vz1 - radius > -this.zNear )
  97. return false;
  98. if( vz1 + radius < -this.zFar )
  99. return false;
  100. // check x
  101. vz1 -= radius;
  102. var perspective = this.projectionMatrix;
  103. var ooZ = 1 / ( perspective.n43 * vz1 );
  104. var ooZscreenCenterX = ooZ * this.screenCenterX;
  105. var vx1 = ( inverse.n11 * vx0 + inverse.n12 * vy0 + inverse.n13 * vz0 + inverse.n14 ) * perspective.n11 * ooZscreenCenterX;
  106. radius = perspective.n11 * radius * ooZscreenCenterX;
  107. if( vx1 + radius < -this.screenCenterX )
  108. return false;
  109. if( vx1 - radius > this.screenCenterX )
  110. return false;
  111. // check y
  112. var vy1 = ( inverse.n21 * vx0 + inverse.n22 * vy0 + inverse.n23 * vz0 + inverse.n24 ) * perspective.n22 * ooZ * this.screenCenterY;
  113. if( vy1 + radius < -this.screenCenterY )
  114. return false;
  115. if( vy1 - radius > this.screenCenterY )
  116. return false;
  117. // inside
  118. object3D.screenPosition.set( vx1, vy1, vz1, radius );
  119. return true;
  120. };