babylon.targetCamera.ts 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. module BABYLON {
  2. export class TargetCamera extends Camera {
  3. public cameraDirection = new BABYLON.Vector3(0, 0, 0);
  4. public cameraRotation = new BABYLON.Vector2(0, 0);
  5. public rotation = new BABYLON.Vector3(0, 0, 0);
  6. public speed = 2.0;
  7. public noRotationConstraint = false;
  8. public lockedTarget = null;
  9. public _currentTarget = BABYLON.Vector3.Zero();
  10. public _viewMatrix = BABYLON.Matrix.Zero();
  11. public _camMatrix = BABYLON.Matrix.Zero();
  12. public _cameraTransformMatrix = BABYLON.Matrix.Zero();
  13. public _cameraRotationMatrix = BABYLON.Matrix.Zero();
  14. public _referencePoint = new BABYLON.Vector3(0, 0, 1);
  15. public _transformedReferencePoint = BABYLON.Vector3.Zero();
  16. public _lookAtTemp = BABYLON.Matrix.Zero();
  17. public _tempMatrix = BABYLON.Matrix.Zero();
  18. public _reset:() => void;
  19. public _waitingLockedTargetId:string;
  20. constructor(name:string, position:Vector3, scene:Scene) {
  21. super(name, position, scene);
  22. }
  23. public _getLockedTargetPosition():Vector3 {
  24. if (!this.lockedTarget) {
  25. return null;
  26. }
  27. return this.lockedTarget.position || this.lockedTarget;
  28. }
  29. // Cache
  30. public _initCache() {
  31. super._initCache();
  32. this._cache.lockedTarget = new BABYLON.Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
  33. this._cache.rotation = new BABYLON.Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
  34. }
  35. public _updateCache(ignoreParentClass?:boolean):void {
  36. if (!ignoreParentClass) {
  37. super._updateCache();
  38. }
  39. var lockedTargetPosition = this._getLockedTargetPosition();
  40. if (!lockedTargetPosition) {
  41. this._cache.lockedTarget = null;
  42. }
  43. else {
  44. if (!this._cache.lockedTarget) {
  45. this._cache.lockedTarget = lockedTargetPosition.clone();
  46. }
  47. else {
  48. this._cache.lockedTarget.copyFrom(lockedTargetPosition);
  49. }
  50. }
  51. this._cache.rotation.copyFrom(this.rotation);
  52. }
  53. // Synchronized
  54. public _isSynchronizedViewMatrix():boolean {
  55. if (!super._isSynchronizedViewMatrix()) {
  56. return false;
  57. }
  58. var lockedTargetPosition = this._getLockedTargetPosition();
  59. return (this._cache.lockedTarget ? this._cache.lockedTarget.equals(lockedTargetPosition) : !lockedTargetPosition)
  60. && this._cache.rotation.equals(this.rotation);
  61. }
  62. // Methods
  63. public _computeLocalCameraSpeed(): number {
  64. var engine = this.getEngine();
  65. return this.speed * ((engine.getDeltaTime() / (engine.getFps() * 10.0)));
  66. }
  67. // Target
  68. public setTarget(target:Vector3):void {
  69. this.upVector.normalize();
  70. BABYLON.Matrix.LookAtLHToRef(this.position, target, this.upVector, this._camMatrix);
  71. this._camMatrix.invert();
  72. this.rotation.x = Math.atan(this._camMatrix.m[6] / this._camMatrix.m[10]);
  73. var vDir = target.subtract(this.position);
  74. if (vDir.x >= 0.0) {
  75. this.rotation.y = (-Math.atan(vDir.z / vDir.x) + Math.PI / 2.0);
  76. } else {
  77. this.rotation.y = (-Math.atan(vDir.z / vDir.x) - Math.PI / 2.0);
  78. }
  79. this.rotation.z = -Math.acos(BABYLON.Vector3.Dot(new BABYLON.Vector3(0, 1.0, 0), this.upVector));
  80. if (isNaN(this.rotation.x)) {
  81. this.rotation.x = 0;
  82. }
  83. if (isNaN(this.rotation.y)) {
  84. this.rotation.y = 0;
  85. }
  86. if (isNaN(this.rotation.z)) {
  87. this.rotation.z = 0;
  88. }
  89. }
  90. public getTarget():Vector3 {
  91. return this._currentTarget;
  92. }
  93. public _decideIfNeedsToMove():boolean {
  94. return Math.abs(this.cameraDirection.x) > 0 || Math.abs(this.cameraDirection.y) > 0 || Math.abs(this.cameraDirection.z) > 0;
  95. }
  96. public _updatePosition():void{
  97. this.position.addInPlace(this.cameraDirection);
  98. }
  99. public _update():void {
  100. var needToMove = this._decideIfNeedsToMove();
  101. var needToRotate = Math.abs(this.cameraRotation.x) > 0 || Math.abs(this.cameraRotation.y) > 0;
  102. // Move
  103. if (needToMove) {
  104. this._updatePosition();
  105. }
  106. // Rotate
  107. if (needToRotate) {
  108. this.rotation.x += this.cameraRotation.x;
  109. this.rotation.y += this.cameraRotation.y;
  110. if (!this.noRotationConstraint) {
  111. var limit = (Math.PI / 2) * 0.95;
  112. if (this.rotation.x > limit)
  113. this.rotation.x = limit;
  114. if (this.rotation.x < -limit)
  115. this.rotation.x = -limit;
  116. }
  117. }
  118. // Inertia
  119. if (needToMove) {
  120. if (Math.abs(this.cameraDirection.x) < BABYLON.Engine.Epsilon) {
  121. this.cameraDirection.x = 0;
  122. }
  123. if (Math.abs(this.cameraDirection.y) < BABYLON.Engine.Epsilon) {
  124. this.cameraDirection.y = 0;
  125. }
  126. if (Math.abs(this.cameraDirection.z) < BABYLON.Engine.Epsilon) {
  127. this.cameraDirection.z = 0;
  128. }
  129. this.cameraDirection.scaleInPlace(this.inertia);
  130. }
  131. if (needToRotate) {
  132. if (Math.abs(this.cameraRotation.x) < BABYLON.Engine.Epsilon) {
  133. this.cameraRotation.x = 0;
  134. }
  135. if (Math.abs(this.cameraRotation.y) < BABYLON.Engine.Epsilon) {
  136. this.cameraRotation.y = 0;
  137. }
  138. this.cameraRotation.scaleInPlace(this.inertia);
  139. }
  140. }
  141. public _getViewMatrix():Matrix {
  142. if (!this.lockedTarget) {
  143. // Compute
  144. if (this.upVector.x != 0 || this.upVector.y != 1.0 || this.upVector.z != 0) {
  145. BABYLON.Matrix.LookAtLHToRef(BABYLON.Vector3.Zero(), this._referencePoint, this.upVector, this._lookAtTemp);
  146. BABYLON.Matrix.RotationYawPitchRollToRef(this.rotation.y, this.rotation.x, this.rotation.z, this._cameraRotationMatrix);
  147. this._lookAtTemp.multiplyToRef(this._cameraRotationMatrix, this._tempMatrix);
  148. this._lookAtTemp.invert();
  149. this._tempMatrix.multiplyToRef(this._lookAtTemp, this._cameraRotationMatrix);
  150. } else {
  151. BABYLON.Matrix.RotationYawPitchRollToRef(this.rotation.y, this.rotation.x, this.rotation.z, this._cameraRotationMatrix);
  152. }
  153. BABYLON.Vector3.TransformCoordinatesToRef(this._referencePoint, this._cameraRotationMatrix, this._transformedReferencePoint);
  154. // Computing target and final matrix
  155. this.position.addToRef(this._transformedReferencePoint, this._currentTarget);
  156. } else {
  157. this._currentTarget.copyFrom(this._getLockedTargetPosition());
  158. }
  159. BABYLON.Matrix.LookAtLHToRef(this.position, this._currentTarget, this.upVector, this._viewMatrix);
  160. return this._viewMatrix;
  161. }
  162. }
  163. }